Compare commits

..

651 Commits

Author SHA1 Message Date
Gregory Schier
083f83ccab Bump version 2024-02-28 08:51:34 -08:00
Gregory Schier
4f749be2e2 Fix dropdown arrow keys 2024-02-28 08:51:08 -08:00
Gregory Schier
cefdc3ecf3 Track GRPC 2024-02-28 07:32:05 -08:00
Gregory Schier
02960d2d64 Analytics ID 2024-02-28 07:27:19 -08:00
Gregory Schier
9e5226aa83 Analytics ID 2024-02-28 07:26:02 -08:00
Gregory Schier
63d7a44586 Remove Escape from hotkeys 2024-02-27 18:58:41 -08:00
Gregory Schier
c851dfe206 Fix sidebar focus 2024-02-27 10:33:20 -08:00
Gregory Schier
6adc15a249 Fix gap in dropdown menu items 2024-02-27 10:27:04 -08:00
Gregory Schier
9ac7aac296 Methods in recent dropdown 2024-02-27 10:20:35 -08:00
Gregory Schier
325d63e1b7 Many hotkey improvements 2024-02-27 10:10:38 -08:00
Gregory Schier
e639a77165 Info logs in build 2024-02-26 17:27:08 -08:00
Gregory Schier
c075efc752 Introspection tweak 2024-02-26 17:24:44 -08:00
Gregory Schier
c4f42f71c3 Tweak editor find/replace 2024-02-26 17:17:37 -08:00
Gregory Schier
535adfe200 Fix find/replace CM styling 2024-02-26 17:07:09 -08:00
Gregory Schier
85fa159f0d Fix lint errors 2024-02-26 07:43:08 -08:00
Gregory Schier
fd2fe46c95 Autocomplete icons and transfer proto files on duplicate 2024-02-26 07:39:53 -08:00
Gregory Schier
6e52f35626 Prompt folder name on create 2024-02-26 07:14:27 -08:00
Gregory Schier
a0d1e7023d Better creation from folder menu 2024-02-26 07:09:59 -08:00
Gregory Schier
97a2f00d59 Auto-fill link to changelog in release script 2024-02-25 18:42:04 -08:00
Gregory Schier
50ad4efad7 Protoc sidecar 2024-02-25 17:43:29 -08:00
Gregory Schier
79a3d9c8df Fix deletion in sidebar 2024-02-25 12:56:57 -08:00
Gregory Schier
b8e20d885f Fix create dropdown hotkey 2024-02-24 22:02:04 -08:00
Gregory Schier
752eb3dbd5 Try changing macOS version 2024-02-24 21:25:58 -08:00
Gregory Schier
616acdfb56 Bump some things 2024-02-24 21:23:02 -08:00
Gregory Schier
b2bcbababe Fix response pane height 2024-02-24 19:31:59 -08:00
Gregory Schier
9f5a3ef96a Don't build plugins 2024-02-24 18:58:51 -08:00
Gregory Schier
d2c5bdc3c8 Remove npm ci plugins 2024-02-24 18:28:07 -08:00
Gregory Schier
0d6899a12c Check in built plugins again 2024-02-24 18:27:36 -08:00
Gregory Schier
1b25cb0c4c Add pkg locks 2024-02-24 18:19:16 -08:00
Gregory Schier
783b7222df Install plugins in CI 2024-02-24 16:29:22 -08:00
Gregory Schier
ff3165ab30 Bump version 2024-02-24 16:22:55 -08:00
Gregory Schier
9780dc88a1 Got json-schema autocomplete working again 2024-02-24 16:22:22 -08:00
Gregory Schier
e4f0d2a341 Proto files off model 2024-02-24 14:16:58 -08:00
Gregory Schier
bcf0ae159d Better gRPC status on error 2024-02-24 12:41:43 -08:00
Gregory Schier
5664d41073 More analytics, and cancel requests 2024-02-24 11:30:07 -08:00
Gregory Schier
e75e6865ea Hook up empty state buttons for first-launch experience 2024-02-23 16:34:19 -08:00
Gregory Schier
fd5b495b70 gRPC in import/export 2024-02-23 16:16:13 -08:00
Gregory Schier
16506d1ddd Everything in messages now 2024-02-22 19:51:30 -08:00
Gregory Schier
e3016f7100 Format XML responses 2024-02-22 01:00:02 -08:00
Gregory Schier
766da4327c Refactor into grpc events 2024-02-22 00:49:22 -08:00
Gregory Schier
6f389b0010 Fix split layout placeholder 2024-02-18 09:12:44 -08:00
Gregory Schier
007ea88edd Add other body type 2024-02-18 08:59:14 -08:00
Gregory Schier
5409678855 Add metadata and squash migrations 2024-02-18 08:35:31 -08:00
Gregory Schier
4c6bd63b8b Better environment edit dialog 2024-02-18 07:44:53 -08:00
Gregory Schier
8db80d2e97 Allow editing base environment 2024-02-18 00:14:47 -08:00
Gregory Schier
c80fca8063 Render gRPC message body 2024-02-18 00:14:26 -08:00
Gregory Schier
7384398813 gRPC authentication 2024-02-17 23:47:28 -08:00
Gregory Schier
b57ea8adeb Even better dropdown filtering 2024-02-17 22:27:01 -08:00
Gregory Schier
8ff2caf3c3 Started gRPC tabs 2024-02-17 22:15:44 -08:00
Gregory Schier
a521b8f308 Better dropdown filtering 2024-02-17 22:03:42 -08:00
Gregory Schier
50ba167516 Prevent dragging folders into itself 2024-02-17 15:32:15 -08:00
Gregory Schier
cb102657ea Fix deps 2024-02-17 15:20:13 -08:00
Gregory Schier
a7d9e2432b Upgrade Vite deps and fix windows DnD 2024-02-17 14:57:12 -08:00
Gregory Schier
d842b168e6 Fix postman importer TS ref 2024-02-17 11:05:57 -08:00
Gregory Schier
870cb25980 Add more info to settings 2024-02-17 11:04:19 -08:00
Gregory Schier
fde0c5540b Adjust placeholder error colors 2024-02-15 21:15:18 -08:00
Gregory Schier
2ec9a1c19d Tweak tab padding 2024-02-15 16:38:14 -08:00
Gregory Schier
c2f5a3bf45 Responsive (scroll) workspace header 2024-02-15 16:30:08 -08:00
Gregory Schier
7c18eeae8c Better button highlight border 2024-02-15 15:55:32 -08:00
Gregory Schier
d7a1b4b7bc Refactor recentRequest/Env/Workspace 2024-02-15 15:14:18 -08:00
Gregory Schier
4566ede184 Better sidebar collapse, debuonce container uqeries, fix recent requests 2024-02-15 15:07:15 -08:00
Gregory Schier
f45c898be0 Better recent work/env/req logic 2024-02-13 17:21:54 -08:00
Gregory Schier
4e1700f8a4 Fix active environment on workspace change 2024-02-13 16:42:07 -08:00
Gregory Schier
f14311d14a Active environment in query param 2024-02-13 16:32:31 -08:00
Gregory Schier
470a7e2278 Better variable placeholder styles 2024-02-13 16:32:17 -08:00
Gregory Schier
2d67be481d Show GQL for graphql requests in sidebar 2024-02-13 16:32:00 -08:00
Gregory Schier
9f6ddb1558 Better highlight on JSON tree 2024-02-13 16:31:38 -08:00
Gregory Schier
853f07b9af Cmd+n to open dropdown 2024-02-11 14:17:09 -08:00
Gregory Schier
0eb6358387 Tab-to-indent in editor 2024-02-11 14:16:36 -08:00
Gregory Schier
d43e045f25 Make editor variables more prominent 2024-02-11 14:16:25 -08:00
Gregory Schier
17432fca29 Fix dropdown open index 2024-02-11 14:16:11 -08:00
Gregory Schier
d5931660c2 Catch URL error when URL = "{{HOST}}" 2024-02-11 09:04:27 -08:00
Gregory Schier
cd7678b7a1 Grap gRPC status codes 2024-02-11 08:52:12 -08:00
Gregory Schier
706be1188b Use basemsg 2024-02-11 08:29:57 -08:00
Gregory Schier
8989b61a13 Combine grpc handlers, fix duplicate 2024-02-10 10:41:45 -08:00
Gregory Schier
a997944f16 Fix response emit and sidebar flex 2024-02-09 16:16:02 -08:00
Gregory Schier
f8e8f5d3f2 Sidebar methods and fix model hooks 2024-02-09 16:09:24 -08:00
Gregory Schier
812e5238ac Fix editor selection/cursor and lint errors 2024-02-09 14:32:58 -08:00
Gregory Schier
16d4f2952d Remove built plugins from source control 2024-02-09 05:09:37 -08:00
Gregory Schier
ac9a6d5871 Merge branch 'grpc' 2024-02-09 05:07:45 -08:00
Gregory Schier
4fcf1df61f Move plugins to build folder 2024-02-09 05:07:34 -08:00
Gregory Schier
394beb374e gRPC Support (#20) 2024-02-09 05:01:00 -08:00
Gregory Schier
ba4d1063e3 Better message serialization 2024-02-09 05:00:48 -08:00
Gregory Schier
2bd9b436e6 Working sidebar actions for grpc 2024-02-07 00:02:02 -08:00
Gregory Schier
915a59dec4 Change hotkey handling to capture phase 2024-02-06 23:44:10 -08:00
Gregory Schier
ae2b746cb2 Fix pool management 2024-02-06 23:26:24 -08:00
Gregory Schier
b04cff153b Minor tweaks 2024-02-06 19:32:03 -08:00
Gregory Schier
bd8e71e567 gRPC schema from files! 2024-02-06 19:20:32 -08:00
Gregory Schier
562a36d616 Proto selection UI/models 2024-02-06 12:29:23 -08:00
Gregory Schier
c85a11edf1 Better reflect failure UI 2024-02-05 14:50:47 -08:00
Gregory Schier
ef7f942a8f Async connection management 2024-02-05 11:29:27 -08:00
Gregory Schier
a7f2a86d71 Refactor model emit, and recent conn dropdown 2024-02-05 10:39:47 -08:00
Gregory Schier
bf90f84d16 db to app_handle! 2024-02-04 22:52:04 -08:00
Gregory Schier
4284aa2549 Single upserted_model event 2024-02-04 21:19:15 -08:00
Gregory Schier
60773cab53 Fix DB mutex deadlock 2024-02-04 21:17:05 -08:00
Gregory Schier
e2c17873ae More messages 2024-02-04 19:08:31 -08:00
Gregory Schier
88982156ee Client streaming working 2024-02-04 17:53:15 -08:00
Gregory Schier
722c8a1c6b Bidirectional working 2024-02-04 14:10:38 -08:00
Gregory Schier
8c15274786 Messages are flowing! 2024-02-04 12:09:10 -08:00
Gregory Schier
1abba4980a Use req/conn/msg models in unary/server 2024-02-04 11:57:12 -08:00
Gregory Schier
3a340999ec Remove console log 2024-02-03 13:39:45 -08:00
Gregory Schier
b7261e77aa Grpc layout use new models 2024-02-03 13:28:31 -08:00
Gregory Schier
23431b40e9 Show gRPC requests in sidebar 2024-02-03 13:08:24 -08:00
Gregory Schier
04f31cd4a7 gRPC models and tables 2024-02-03 11:14:42 -08:00
Gregory Schier
7d82a7e74a Tiny fixes 2024-02-02 18:41:00 -08:00
Gregory Schier
d31255d987 Better formatting 2024-02-02 13:37:44 -08:00
Gregory Schier
e53693f605 A bit better handling of responses 2024-02-02 13:32:06 -08:00
Gregory Schier
67aa7b7268 Split layouts and things 2024-02-02 12:41:37 -08:00
Gregory Schier
e27ed9becc bidi hacked! 2024-02-02 01:10:54 -08:00
Gregory Schier
22d21af3c2 Implement cancel 2024-02-02 00:18:37 -08:00
Gregory Schier
67000af7f9 Better connection management 2024-02-01 20:29:32 -08:00
Gregory Schier
b84c7ba50c gRPC manager mostly working 2024-02-01 15:36:50 -08:00
Gregory Schier
a0b3f86462 Small refactor 2024-02-01 02:42:59 -08:00
Gregory Schier
6a8395660d Refactor commands and DB 2024-02-01 02:29:24 -08:00
Gregory Schier
2c041fbac6 Some minor tweaks 2024-02-01 00:48:03 -08:00
Gregory Schier
1eed0e8f22 Revert response JSON tree 2024-02-01 00:38:57 -08:00
Gregory Schier
63a0ed273d Even better styles 2024-02-01 00:36:49 -08:00
Gregory Schier
d0be5ca515 Styled it up a bit 2024-02-01 00:16:09 -08:00
Gregory Schier
b964c942d6 Merge remote-tracking branch 'origin/grpc' into grpc 2024-01-31 22:14:15 -08:00
Gregory Schier
a05fc5fd20 Hacky server streaming done 2024-01-31 22:14:08 -08:00
Gregory Schier
de183abd24 Hacky client streaming done 2024-01-31 22:13:46 -08:00
Gregory Schier
5c44df7b00 Initial frontend for gRPC UI 2024-01-30 16:43:54 -08:00
Gregory Schier
dbdce4cf9a Hooked up test call from frontend! 2024-01-29 20:50:43 -08:00
Gregory Schier
219a6b78da Fix cookie jar 2024-01-28 17:49:04 -08:00
Gregory Schier
fb11aff03f Track dialogs 2024-01-28 16:33:36 -08:00
Gregory Schier
15714ae188 Fix dropdown separator 2024-01-28 16:21:41 -08:00
Gregory Schier
ce116d032d Better format 2024-01-28 16:19:46 -08:00
Gregory Schier
6f41df6e52 More response info 2024-01-28 16:02:49 -08:00
Gregory Schier
0853d2ca95 Better BG color 2024-01-28 14:43:04 -08:00
Gregory Schier
6798331ce5 Cookie Support (#19) 2024-01-28 14:39:51 -08:00
Gregory Schier
5ffc75e0ad Add shift to hotkey dialog hotkey 2024-01-19 22:11:20 -08:00
Gregory Schier
bf92371a49 Show alert after force checking updates 2024-01-19 22:11:02 -08:00
Gregory Schier
bd3da86317 Better dialog padding 2024-01-19 22:08:32 -08:00
Gregory Schier
3db3d42246 Change env hotkey to use shift 2024-01-19 21:53:48 -08:00
Gregory Schier
de8bf3ca70 Fix URL 2px grow on focus 2024-01-19 21:49:51 -08:00
Gregory Schier
8bc131de6c Bump version 2024-01-19 13:42:02 -08:00
Gregory Schier
efce69292d Fix analytics again 2024-01-18 22:28:25 -08:00
Gregory Schier
0ccc893440 Fix dialog close button 2024-01-18 20:57:42 -08:00
Gregory Schier
1f9756c917 Fix URLBar expanded state inner buttons 2024-01-18 20:40:56 -08:00
Gregory Schier
be8f0e4521 Some analytics fixes 2024-01-18 20:23:02 -08:00
Gregory Schier
bcdf51d231 Launch analytics events, changelog, better filter styles 2024-01-18 14:42:02 -08:00
Gregory Schier
1a1553eebd Bump version 2024-01-17 14:56:47 -08:00
Gregory Schier
321c3862fe Custom HTTP method names 2024-01-17 14:52:19 -08:00
Gregory Schier
466d412e65 Workspace header tweak Windows 2024-01-17 18:48:43 -08:00
Gregory Schier
86f50b826f Fix header in fullscreen mode on Mac 2024-01-17 09:34:47 -08:00
Gregory Schier
ac1e646e68 Download response, and some fixes 2024-01-16 17:02:55 -08:00
Gregory Schier
33374eefc7 Fix editor toolbar blocking things 2024-01-15 21:44:53 -08:00
Gregory Schier
7047df4f7e Better request creation (Closes #14) 2024-01-15 21:39:27 -08:00
Gregory Schier
c8bd4d0ae0 XPath plugin 2024-01-15 21:27:47 -08:00
Gregory Schier
1e79f76701 Fix send icon 2024-01-15 15:43:55 -08:00
Gregory Schier
18852dca06 Switch to Lucide icons 2024-01-15 15:42:28 -08:00
Gregory Schier
408e7e80b7 Improve response filter UX 2024-01-15 15:19:29 -08:00
Gregory Schier
fc185de023 JSONPath filter plugins working 2024-01-15 15:06:49 -08:00
Gregory Schier
bb9d3a42f3 Move plugin stuff around 2024-01-15 14:33:51 -08:00
Gregory Schier
baf0f4291d Fix request duplication 2024-01-15 13:47:44 -08:00
Gregory Schier
536066142c Fix workspace defaults 2024-01-15 12:25:13 -08:00
Gregory Schier
04cf16497d Better settings dialog 2024-01-15 12:16:44 -08:00
Gregory Schier
feb5972090 Fix resize observer 2024-01-15 12:02:08 -08:00
Gregory Schier
77bf5a58d8 Move request-related settings to workspace 2024-01-15 11:52:36 -08:00
Gregory Schier
3539642491 Bump beta version 2024-01-14 20:30:25 -08:00
Gregory Schier
08abea6a6f fix mac decorations 2024-01-14 17:22:31 -08:00
Gregory Schier
0045b85f00 Integrated titlebar windows 2024-01-14 16:44:04 -08:00
Gregory Schier
4b34c3d101 Further titlebar tweaks 2024-01-14 12:02:44 -08:00
Gregory Schier
4af0a15d9f Better titlebar control icons 2024-01-14 11:56:21 -08:00
Gregory Schier
3a4a76c58d Basic Linux/Windows integrated titlebar 2024-01-13 23:40:32 -08:00
Gregory Schier
3086d815c1 Fix hotkey formatting 2024-01-12 22:12:01 -08:00
Gregory Schier
a48a9eab4a beta tag 2024-01-12 22:00:55 -08:00
Gregory Schier
48664c66e5 fix appearance init 2024-01-12 21:59:46 -08:00
Gregory Schier
7aee5176a9 Vendor Openssl 2024-01-12 21:03:28 -08:00
Gregory Schier
0da68ced18 Hotkeys for request switcher 2024-01-12 21:03:20 -08:00
Gregory Schier
39f7d9c113 Appearance setting and gzip/etc support 2024-01-12 13:39:08 -08:00
Gregory Schier
138943bfb6 Initial settings implementation 2024-01-11 21:13:17 -08:00
Gregory Schier
c1c9f882a6 Dropdown manages hotkeys now 2024-01-11 10:18:05 -08:00
Gregory Schier
1bcf26f656 Hotkey for keyboard shortcut help 2024-01-10 22:05:16 -08:00
Gregory Schier
7c2466da5e Bump version number 2024-01-10 16:25:55 -08:00
Gregory Schier
7dc78a1f6f Add hotkey dialog and rust-only analytics 2024-01-10 16:18:08 -08:00
Gregory Schier
88d024023b Fix beta icon 2024-01-08 17:07:42 -08:00
Gregory Schier
626aacf982 Bump version to 2024.0.0 2024-01-08 15:57:59 -08:00
Gregory Schier
d5855c45a6 Hotkey labels 2024-01-08 15:57:21 -08:00
Gregory Schier
793bff9f27 Show hotkeys on empty views 2024-01-08 15:13:44 -08:00
Gregory Schier
88ea68e72f Remove base env, fix hotkeys, and QoL improvements 2024-01-07 22:24:19 -08:00
Gregory Schier
35e40d2c55 Fix hotkeys getting stuck on cmd+tab 2024-01-07 21:32:25 -08:00
Gregory Schier
c472b83409 Always show settings dropdown 2023-11-22 09:39:30 -08:00
Gregory Schier
52c26d235c Tweak margin 2023-11-22 09:37:50 -08:00
Gregory Schier
ac54729012 Fix bottom-up dropdown positioning 2023-11-22 09:35:56 -08:00
Gregory Schier
0586034ef4 Bump version 2023-11-22 09:06:47 -08:00
Gregory Schier
91790ba708 Better linux/Windows support for hotkeys 2023-11-22 09:06:22 -08:00
Gregory Schier
d8ab6c0b50 Good hotkey support 2023-11-22 09:01:48 -08:00
Gregory Schier
b600a21a2b Reset URL bar when request changes 2023-11-21 23:26:29 -08:00
Gregory Schier
4f9d1278f7 Env dialog hotkey 2023-11-21 22:35:28 -08:00
Gregory Schier
15aa93f5f9 Remove response body and basic hotkeys 2023-11-21 22:15:01 -08:00
Gregory Schier
c7798092d8 Remove app-specific menu items 2023-11-21 19:18:40 -08:00
Gregory Schier
5560593aaa Fix macOS menu and fallback URL 2023-11-21 09:24:13 -08:00
Gregory Schier
66639e651d Hide menu on windows/linux 2023-11-21 08:17:37 -08:00
Gregory Schier
8e42d5ccdb Disable sandboxing (again) 2023-11-19 21:59:55 -08:00
Gregory Schier
5c62594087 Fix drag-drop reorder 2023-11-19 21:43:01 -08:00
Gregory Schier
26b6c48657 Postman ID generation 2023-11-19 20:54:02 -08:00
Gregory Schier
0290aba982 Bump beta.3 2023-11-19 20:46:55 -08:00
Gregory Schier
0bafc4e4f5 Postman variables + urlencoded forms 2023-11-19 20:29:24 -08:00
Gregory Schier
9a36f94279 Add back Windows/Linux builds 2023-11-19 18:22:13 -08:00
Gregory Schier
1d8e66179e Remove Tauri context menu plugin 2023-11-19 18:21:10 -08:00
Gregory Schier
fda6d16d8e Fix header padding windows/linux 2023-11-19 18:14:49 -08:00
Gregory Schier
c4737916df Some tweaks 2023-11-19 18:13:32 -08:00
Gregory Schier
919465cdbb Beta 2 2023-11-19 17:41:58 -08:00
Gregory Schier
de3730fa4f Network entitlement 2023-11-19 17:41:46 -08:00
Gregory Schier
aff26fdd46 Try sandboxing again 2023-11-19 17:06:31 -08:00
Gregory Schier
3c0edf06af Remove sandboxing 2023-11-17 09:33:16 -08:00
Gregory Schier
cb8939db88 touch 2023-11-17 08:00:04 -08:00
Gregory Schier
bf4b3213c4 Out of beta 2023-11-17 07:53:26 -08:00
Gregory Schier
633d7c52c4 Tweak 2023-11-17 07:52:03 -08:00
Gregory Schier
0401cb92aa Format GraphQL variables 2023-11-17 07:51:03 -08:00
Gregory Schier
bff6c668a0 Drag into folder (Closes #8) 2023-11-17 07:36:01 -08:00
Gregory Schier
ee87e65763 Mostly move some stuff around 2023-11-16 18:53:34 -08:00
Gregory Schier
f165a0b827 Better update logic 2023-11-14 14:28:06 -08:00
Gregory Schier
f7426dc8ce Better dropdown menu 2023-11-14 10:56:56 -08:00
Gregory Schier
6114039f7e Version to beta 2023-11-14 10:07:39 -08:00
Gregory Schier
da414debe1 Beta channel updates 2023-11-14 08:57:46 -08:00
Gregory Schier
11f5541558 Multipart form UI and fixes 2023-11-14 00:32:02 -08:00
Gregory Schier
1bc155d684 Got multipart working (text-only) 2023-11-13 23:26:11 -08:00
Gregory Schier
335231060e Fix window title moving stoplights (for now) 2023-11-13 23:25:47 -08:00
Gregory Schier
0fdf64440f Postman import form data 2023-11-13 11:48:28 -08:00
Gregory Schier
a984fb33dc Some small improvements 2023-11-13 11:44:29 -08:00
Gregory Schier
41b1ec96c9 Form urlencoded bodies! 2023-11-13 11:28:37 -08:00
Gregory Schier
df83a61d6f Url parameters done 2023-11-13 10:52:11 -08:00
Gregory Schier
d289f1fd13 Minor tweaks 2023-11-12 21:16:42 -08:00
Gregory Schier
aea4e961aa Custom updater code 2023-11-12 21:16:33 -08:00
Gregory Schier
c554b73d48 Request body is now an object 2023-11-12 11:16:12 -08:00
Gregory Schier
b519bff3d6 Some postman import improvements 2023-11-11 10:43:11 -08:00
Gregory Schier
8381104302 Sync window title (Closes #13) 2023-11-10 15:55:50 -08:00
Gregory Schier
5ef7c6a1a2 Dev app icon 2023-11-10 13:06:12 -08:00
Gregory Schier
6d7a81850c Upgrade sqlx 2023-11-10 12:28:33 -08:00
Gregory Schier
6e5d5fcb95 Clean up importers 2023-11-10 11:39:17 -08:00
Gregory Schier
004fef6729 Fix is_empty check 2023-11-10 09:12:20 -08:00
Gregory Schier
0bec5a6405 Postman importer semi-complete 2023-11-10 09:08:20 -08:00
Gregory Schier
60b091ff1c Tidy up logs and general cleanup 2023-11-09 20:33:09 -08:00
Gregory Schier
bee1a5cb2d Move error alert to hook 2023-11-09 20:02:42 -08:00
Gregory Schier
bb2d3dd5b1 Show import errors 2023-11-09 20:00:19 -08:00
Gregory Schier
bf8aad04c7 Hacky Yaak import complete! 2023-11-09 19:40:31 -08:00
Gregory Schier
4306294a72 More fallback request handing 2023-11-09 17:42:10 -08:00
Gregory Schier
10f3722fe3 Request fallback name in header 2023-11-09 17:34:57 -08:00
Gregory Schier
c1af9ca44a Better default request names 2023-11-09 17:26:04 -08:00
Gregory Schier
5b230c74f0 Better non-named requests 2023-11-09 17:17:03 -08:00
Gregory Schier
5cebb4e61a Better Yaak export 2023-11-09 17:03:29 -08:00
Gregory Schier
bd9d1e2244 Refactor previous commit 2023-11-09 16:50:57 -08:00
Gregory Schier
9bdaa05f00 Default request name to URL(ish) 2023-11-09 16:47:00 -08:00
Gregory Schier
750ad0c902 Rename initial workspace to "Yaak" 2023-11-09 13:17:21 -08:00
Gregory Schier
a9c16838e6 No analytics in dev 2023-11-09 11:46:52 -08:00
Gregory Schier
d5065ab6d9 Analytics event properties 2023-11-09 11:44:59 -08:00
Gregory Schier
9ebb3ef532 Context menu, logs in DevTools, export, tweaks 2023-11-09 09:28:01 -08:00
Gregory Schier
aeda72f13e Fix plugin (again) 2023-11-08 13:33:15 -08:00
Gregory Schier
83aa9041cb Bundle plugin in Git 2023-11-08 13:06:49 -08:00
Gregory Schier
d51913509d Move plugins back 2023-11-08 12:34:14 -08:00
Gregory Schier
5106f28ba5 Fix permissions 2023-11-08 12:02:17 -08:00
Gregory Schier
0c55c6eaab Bump version 2023-11-08 10:12:01 -08:00
Gregory Schier
b0edbd19c8 Tweak theme 2023-11-08 10:11:29 -08:00
Gregory Schier
7630db79b7 Tweak theme 2023-11-08 09:56:13 -08:00
Gregory Schier
55a7b82567 Track screen size, os, and version 2023-11-08 09:49:29 -08:00
Gregory Schier
b5cb46918a Rust analytics and a few tweaks 2023-11-08 09:13:32 -08:00
Gregory Schier
a793ece1a5 Add basic analytics 2023-11-07 09:53:59 -08:00
Gregory Schier
0f6e4b641a Cancel responses on startup 2023-11-06 13:06:15 -08:00
Gregory Schier
5ac5fab0c6 Send all in a folder 2023-11-06 10:53:39 -08:00
Gregory Schier
8030a8a235 Rework workspace header 2023-11-06 10:42:59 -08:00
Gregory Schier
d98426cad3 Fix sidebar focus max recursion 2023-11-06 10:40:02 -08:00
Gregory Schier
06034a8fc4 Save after formatting GraphQL (Closes #9) 2023-11-06 07:20:47 -08:00
Gregory Schier
1ee9f9bb51 Move plugins back to root dir 2023-11-06 07:18:53 -08:00
Gregory Schier
4b99d1405e Persist sidebar collapsed state (Closes #10) 2023-11-06 07:18:42 -08:00
Gregory Schier
8480e52195 Vite to bundle insomnia plugin 2023-11-05 22:13:22 -08:00
Gregory Schier
243e65a992 Better import conversion 2023-11-05 14:46:08 -08:00
Gregory Schier
b82304a233 Basic import of request body and bearer auth 2023-11-05 14:35:25 -08:00
Gregory Schier
f7a4ea9735 Recursive Insomnia import! 2023-11-05 13:33:23 -08:00
Gregory Schier
33d1a84ecd Remove numbers from recent requests 2023-11-04 16:19:21 -07:00
Gregory Schier
f4a071ee05 Fix drop marker indent 2023-11-04 11:16:41 -07:00
Gregory Schier
e26ba0f9d0 Folder actions 2023-11-04 10:48:18 -07:00
Gregory Schier
b4e2a12375 Folder chevron icon 2023-11-03 23:10:44 -07:00
Gregory Schier
5e7aacd31a Fix arrow navigation for nested sidebar 2023-11-03 17:29:33 -07:00
Gregory Schier
00718df49e Folder-based drag-n-drop complete! 2023-11-03 16:29:21 -07:00
Gregory Schier
bb9025ab07 Sidebar ordering 95% done! 2023-11-03 15:02:17 -07:00
Gregory Schier
867f3908ed Nested sidebar ordering almost working 2023-11-03 14:08:46 -07:00
Gregory Schier
30e1ecac39 Add folder model 2023-11-03 07:49:44 -07:00
Gregory Schier
7eb2abe9b2 Even better focus state 2023-11-02 22:23:21 -07:00
Gregory Schier
a5ac8fa035 Remove focus on env sidebar buttons 2023-11-02 22:18:13 -07:00
Gregory Schier
dd705de155 Rearrange menus 2023-11-02 21:41:35 -07:00
Gregory Schier
b15cdec701 Refactor environment edit dialog 2023-11-02 20:38:33 -07:00
Gregory Schier
a99a36b5cc Base environments fully working 2023-11-02 18:43:39 -07:00
Gregory Schier
e0b0e3d781 Initial "plugin" system with importer (#7) 2023-11-02 18:08:43 -07:00
Gregory Schier
98a4834d4f Fix cursor color in single-line mode 2023-10-31 15:10:33 -07:00
Gregory Schier
32b135dbaf Fix sending of ephemeral requests 2023-10-30 08:24:49 -07:00
Gregory Schier
0fc8d12a06 Fix GQL introspection and bearer auth templating 2023-10-30 08:07:34 -07:00
Gregory Schier
3c2bdab101 Fix button styles 2023-10-30 07:27:27 -07:00
Gregory Schier
8b5d7ae3ed Fix editor stale callbacks and recent item deletion 2023-10-30 07:07:14 -07:00
Gregory Schier
51949f4fbf Refactored some core UI 2023-10-30 06:35:52 -07:00
Gregory Schier
6013cd2329 Plugin module loading 2023-10-29 20:50:23 -07:00
Gregory Schier
eba28ade48 Bump version 2023-10-29 17:22:27 -07:00
Gregory Schier
44af1ddc8a Fix sidebar scroll 2023-10-29 17:19:03 -07:00
Gregory Schier
63c0d09df8 A bit more playing with JS runtime 2023-10-29 17:05:48 -07:00
Gregory Schier
f305633d94 Initial "Hello World" for plugins 2023-10-29 16:43:28 -07:00
Gregory Schier
13155f8591 Fix request creation 2023-10-29 12:05:05 -07:00
Gregory Schier
f2ac97aa62 Restore recent environment on workspace change
Fixes #6
2023-10-29 11:32:55 -07:00
Gregory Schier
18eb0027a1 Fix var complete and env dialog actions 2023-10-29 11:18:55 -07:00
Gregory Schier
9e2803fcfb Remove broken key/value enter/backspace logic 2023-10-29 10:45:05 -07:00
Gregory Schier
705e30b6e0 Delete key/value on backspace 2023-10-29 10:26:38 -07:00
Gregory Schier
f1260911ea Move workspace menu, better env mgmt, QoL 2023-10-29 09:45:16 -07:00
Gregory Schier
076ff63dbe Bump version 2023-10-28 23:41:58 -07:00
Gregory Schier
899092b4d2 Better listening for path changes 2023-10-28 23:41:24 -07:00
Gregory Schier
c2c3a28aab Bump version 2023-10-28 22:14:51 -07:00
Gregory Schier
25c0db502e Fixed auto-focus in prompt and env dropdown 2023-10-28 22:14:12 -07:00
Gregory Schier
6dcbe45a53 Clear selected sidebar index on drag-drop end 2023-10-28 21:47:00 -07:00
Gregory Schier
e2b46f25ff Revert debug name 2023-10-28 21:43:09 -07:00
Gregory Schier
981182be46 Fix drag-n-drop things 2023-10-28 21:42:35 -07:00
Gregory Schier
ad164ebd5e Persist window paths 2023-10-28 21:23:46 -07:00
Gregory Schier
cacdad8826 Bump version to 2023.1.0 2023-10-28 19:15:33 -07:00
Gregory Schier
77e5142a7c Update placeholders when env changes 2023-10-28 19:14:51 -07:00
Gregory Schier
613081728d Placeholder error and fix env nav 2023-10-28 19:08:31 -07:00
Gregory Schier
23e77dfec1 Recent requests/workspaces. Closes #1 2023-10-28 18:46:54 -07:00
Gregory Schier
6e273ae2a3 Fix recent requests loading on startup 2023-10-28 18:27:18 -07:00
Gregory Schier
4061094988 Add tauri window save state plugin 2023-10-28 13:14:27 -07:00
Gregory Schier
82b185e27f Fix rustfmt 2023-10-28 12:45:25 -07:00
Gregory Schier
27dc261639 Handle enabled/disabled variables and render multi 2023-10-28 11:36:40 -07:00
Gregory Schier
7e45fecf19 Remove unused Variable type 2023-10-28 11:31:45 -07:00
Gregory Schier
1a5053380b Variables under Environment, and render all props 2023-10-28 11:29:29 -07:00
Gregory Schier
408665c62d Native Codemirror cursor 2023-10-27 13:14:41 -07:00
Gregory Schier
65efee2048 Only wrap URLBar on focus and hotkey to open recent requests 2023-10-27 12:40:43 -07:00
Gregory Schier
3faa66a1fc Resizing window no longer changes sidebar visibility
Fixes #4
2023-10-27 11:21:59 -07:00
Gregory Schier
9dafe4f704 Auto-expand URL bar height 2023-10-27 10:57:07 -07:00
Gregory Schier
356eaf1713 Environment deletion and better actions menu 2023-10-26 16:18:47 -07:00
Gregory Schier
f8584f1537 Stop autocomplete from jumping around 2023-10-26 15:27:48 -07:00
Gregory Schier
6ad6cb34b0 Fix request creation from menu 2023-10-26 10:41:14 -07:00
Gregory Schier
32b27cd780 Send requests with active environment 2023-10-26 10:32:06 -07:00
Gregory Schier
0344a1e8c9 Move create request and fix slow HTML highlighting 2023-10-26 09:42:19 -07:00
Gregory Schier
0515271c12 Better project selector, Fixes #2, and a bunch more 2023-10-26 09:11:44 -07:00
Gregory Schier
5ae8d54ce0 Fixed some routing and introspection requests 2023-10-25 21:53:18 -07:00
Gregory Schier
33c406ce49 Environments in URL and better rendering 2023-10-25 11:13:00 -07:00
Gregory Schier
3b660ddbd0 Move responses dropdown to separate component 2023-10-25 07:59:10 -07:00
Gregory Schier
3132728a27 Fix dialog height 2023-10-25 00:02:51 -07:00
Gregory Schier
7063128342 Better style when no active environment 2023-10-24 23:58:12 -07:00
Gregory Schier
2187775462 Environment dropdown and actions 2023-10-24 09:17:29 -07:00
Gregory Schier
18adcd1004 Started on environment edit dialog 2023-10-23 21:00:36 -07:00
Gregory Schier
b0656d1e38 Hacky implementation of variable autocomplete 2023-10-23 10:31:21 -07:00
Gregory Schier
38e66047e0 Rendered first variable! 2023-10-22 22:30:29 -07:00
Gregory Schier
c24f049dac Updating environments! 2023-10-22 22:06:51 -07:00
Gregory Schier
53d13c8172 Update .gitignore 2023-10-22 20:40:00 -07:00
Gregory Schier
0727c6e437 Prettier and start of env editor 2023-10-22 20:38:57 -07:00
Gregory Schier
8328d20150 Environments data model 2023-10-22 18:28:56 -07:00
Gregory Schier
afe6a3bf57 Environment data model backend 2023-10-22 16:05:09 -07:00
Gregory Schier
d920632cbd Fix some eslint warnings 2023-10-22 11:02:39 -07:00
Gregory Schier
5c456fd4d5 Add APPLE_TEAM_ID 2023-10-18 14:12:08 -07:00
Gregory Schier
38c247e350 Revert artifacts things 2023-10-18 13:25:35 -07:00
Gregory Schier
0c8f72124a Bump cargo deps 2023-10-18 13:25:20 -07:00
Gregory Schier
80ed6b1525 Bump version 2023-10-18 12:14:38 -07:00
Gregory Schier
4424b3f208 Fix sidebar drag-n-drop 2023-10-18 11:58:58 -07:00
Gregory Schier
2c75abce09 Retry button on introspection errors 2023-06-12 13:20:42 -07:00
Gregory Schier
4e15eb197f Fix autocomplete doc font size 2023-05-31 21:32:48 -07:00
Gregory Schier
a7544b4f8c Persist introspection queries and also improve 2023-05-31 21:29:41 -07:00
Gregory Schier
d126aad172 Update tauri NPM 2023-05-29 12:49:50 -07:00
Gregory Schier
acc5c0de50 Fix graphql instrospection 2023-05-29 12:31:34 -07:00
Gregory Schier
3391da111d Change version 2023-04-27 16:53:39 -07:00
Gregory Schier
e37ce96956 Version 1.0.0 2023-04-27 16:47:49 -07:00
Gregory Schier
c51831c975 Fix window methods on Linux/Windows 2023-04-27 16:27:02 -07:00
Gregory Schier
180aa39de4 Cross platform window controls 2023-04-27 10:19:49 -07:00
Gregory Schier
3bd780782e Fix ubuntu build 2023-04-26 17:00:30 -07:00
Gregory Schier
f9ba2f79c2 Windows and Linux 2023-04-26 16:54:51 -07:00
Gregory Schier
d9493de2be Bump version 2023-04-26 16:47:50 -07:00
Gregory Schier
bc9a623742 Very basic CSV viewer 2023-04-22 21:53:04 +08:00
Gregory Schier
532edbf274 Truncate response files 2023-04-14 14:15:33 -07:00
Gregory Schier
1585692328 Randomly offset new windows 2023-04-14 14:05:23 -07:00
Gregory Schier
083f565b12 Fix text encoding and delete responses 2023-04-14 13:50:41 -07:00
Gregory Schier
f7f7438c9e Delete response files 2023-04-14 12:17:11 -07:00
Gregory Schier
19934a93bb Readonly editor disable tabindex 2023-04-13 22:36:11 -07:00
Gregory Schier
577cfe5bdc Fix imageview padding 2023-04-13 22:33:47 -07:00
Gregory Schier
43ac6afae1 Duration and size tags 2023-04-13 20:50:17 -07:00
Gregory Schier
8cc11703d3 Comment 2023-04-13 18:55:32 -07:00
Gregory Schier
4f7a116378 Always store response on filesystem 2023-04-13 18:52:56 -07:00
Gregory Schier
513793d9ce Support binary responses! 2023-04-13 18:48:40 -07:00
Gregory Schier
67f32b6734 Blur backdrop 2023-04-11 16:12:26 -07:00
Gregory Schier
66813d67fe Autofocus buttons 2023-04-11 14:04:23 -07:00
Gregory Schier
a38691ed53 Better opening workspaces and redirect workspace to recent request 2023-04-11 11:11:36 -07:00
Gregory Schier
deeefdcfbf Button disabled style opacity 2023-04-10 16:03:45 -07:00
Gregory Schier
db292511b1 Dropdown keys and pointer events 2023-04-10 16:02:29 -07:00
Gregory Schier
1a5334c1ce Upgrade deno core 2023-04-10 11:16:25 -07:00
Gregory Schier
11002abe39 Tweak response history 2023-04-09 23:15:51 -07:00
Gregory Schier
d922dcb062 Fixed multi-window model sync 2023-04-09 22:32:47 -07:00
Gregory Schier
6fcaa18e86 Tweak recent requests 2023-04-09 22:25:00 -07:00
Gregory Schier
7664c941dd Toggle settings 2023-04-09 22:12:16 -07:00
Gregory Schier
6f5cb528c6 Fix sidebar request focus 2023-04-09 22:03:41 -07:00
Gregory Schier
ebb78922f0 More stuff on sidebar 2023-04-09 21:52:04 -07:00
Gregory Schier
2285fe9f1c Small tweaks 2023-04-09 15:32:13 -07:00
Gregory Schier
38ba8625d8 Request history navigator 2023-04-09 15:26:54 -07:00
Gregory Schier
ab5681c7ad Enter name on create workspace 2023-04-09 12:27:02 -07:00
Gregory Schier
f66dcb9267 Rename workspace 2023-04-09 12:23:41 -07:00
Gregory Schier
1b6cfbac77 Sidebar hover transitions 2023-04-06 16:30:46 -07:00
Gregory Schier
4c27e788ea Remove some more key value usage 2023-04-06 16:26:56 -07:00
Gregory Schier
769da0b052 A bunch of tweaks 2023-04-06 16:05:25 -07:00
Gregory Schier
6b60c86300 macOS 12 2023-04-06 08:39:30 -07:00
Gregory Schier
30c1b5e8c7 Remove system tray icon 2023-04-06 08:15:40 -07:00
Gregory Schier
10af9b6f99 Minor tweaks 2023-04-04 17:21:02 -07:00
Gregory Schier
aa8c066f2d Fix some things 2023-04-04 16:56:45 -07:00
Gregory Schier
b913b74449 Editor line wrapping support (not used yet) 2023-04-04 16:40:37 -07:00
Gregory Schier
b71adce50b remove janky last location tracking 2023-04-04 16:23:08 -07:00
Gregory Schier
0fbb44c701 Fix resize cursor 2023-04-04 16:12:45 -07:00
Gregory Schier
de335e8637 Better button styles 2023-04-04 15:40:25 -07:00
Gregory Schier
2999f63a4c Bump version 2023-04-04 13:56:24 -07:00
Gregory Schier
2abc5e6f0b Some small fixes 2023-04-04 13:56:14 -07:00
Gregory Schier
639de4321e A few fixes 2023-04-04 13:31:48 -07:00
Gregory Schier
b3c461afdd Better status tags and delete request on key 2023-04-04 12:36:30 -07:00
Gregory Schier
7d154800a0 Remove expects from request sending 2023-04-04 08:14:32 -07:00
Gregory Schier
b48ed0399e Fix web view height 2023-04-04 07:51:41 -07:00
Gregory Schier
c5d6e7d74a Fix autocomplete spacing 2023-04-04 07:51:19 -07:00
Gregory Schier
e82f915363 Fix input focus border 2023-04-03 12:19:37 -07:00
Gregory Schier
3128e9ce76 Hot keys and cleanup 2023-04-03 07:59:49 -07:00
Gregory Schier
bc0e86757c Add entitlemet for v8 2023-04-02 20:23:21 -07:00
Gregory Schier
fec99916c2 Debug codesigned build 2023-04-02 19:09:14 -07:00
Gregory Schier
3b5d059b11 Disable code signing 2023-04-02 18:27:14 -07:00
Gregory Schier
c3fe2acc8a Fix tauri script command 2023-04-02 17:25:24 -07:00
Gregory Schier
4d002c412b Fix universal binary 2023-04-02 17:12:20 -07:00
Gregory Schier
46d152b5f1 Bump version 2023-04-02 15:44:41 -07:00
Gregory Schier
25fa81ebbc Fix toolchain 2023-04-02 15:44:21 -07:00
Gregory Schier
7c2de3c360 Add proper target 2023-04-02 15:42:19 -07:00
Gregory Schier
3a3b187cd0 Try universal binary 2023-04-02 15:33:13 -07:00
Gregory Schier
3226bbe083 Fix version 2023-04-02 15:25:24 -07:00
Gregory Schier
a1e4e0e6c9 Bump version 2023-04-02 14:54:41 -07:00
Gregory Schier
b3aa8b893b Notorization (hopefully) 2023-04-02 14:53:49 -07:00
Gregory Schier
f057139634 Change tabs again 2023-04-02 11:11:53 -07:00
Gregory Schier
71a2b11ab4 Better response headers 2023-04-02 10:45:41 -07:00
Gregory Schier
587254a0e7 Show response headers 2023-04-01 23:43:22 -07:00
Gregory Schier
9f4de66f3c Some more refactoring 2023-04-01 21:48:30 -07:00
Gregory Schier
b0d8908724 Refactor debounce and tauri event listeners 2023-04-01 21:39:46 -07:00
Gregory Schier
15c22d98c6 Fix dropdown and dialog key handling 2023-04-01 21:04:39 -07:00
Gregory Schier
3105ae0edc Refactor sidebar display 2023-04-01 20:58:53 -07:00
Gregory Schier
11a89f06c1 Better GraphQL schema fetching 2023-04-01 17:53:36 -07:00
Gregory Schier
9cbe24e740 More eslint fixes 2023-04-01 15:48:37 -07:00
Gregory Schier
bfbed13b8f Add React hooks eslint 2023-04-01 15:26:57 -07:00
Gregory Schier
2268de6321 Fix Tauri listeners 2023-04-01 00:02:17 -07:00
Gregory Schier
dd99aa7fcd Memo editor 2023-03-31 23:19:15 -07:00
Gregory Schier
be436bb706 Fix request duplication 2023-03-31 22:54:32 -07:00
Gregory Schier
bd48726f44 Fix tauri listeners causing too many updates 2023-03-31 22:48:34 -07:00
Gregory Schier
10bea83f98 Remove import 2023-03-31 22:42:41 -07:00
Gregory Schier
8122b4fb84 Fix 2023-03-31 22:42:26 -07:00
Gregory Schier
3ae57fb2d8 Upgrade Deno 2023-03-31 22:42:08 -07:00
Gregory Schier
6dc3eecca4 Tweak 2023-03-31 16:14:25 -07:00
Gregory Schier
9d1d732154 Fix send hotkey 2023-03-31 16:13:34 -07:00
Gregory Schier
8a117415b7 Better schema fetching 2023-03-31 16:02:09 -07:00
Gregory Schier
d36623ebc9 Finally fix the editor! 2023-03-31 15:56:35 -07:00
Gregory Schier
94a3ae3696 Fix editor blurring bug! 2023-03-31 13:53:28 -07:00
Gregory Schier
2836a28988 Better model updates 2023-03-31 13:21:02 -07:00
Gregory Schier
946d7dc89e Fix text obscuring 2023-03-30 17:22:52 -07:00
Gregory Schier
af6300f18b Button ring colors 2023-03-30 17:17:07 -07:00
Gregory Schier
905cb4b18e Remove dummy button 2023-03-30 17:12:38 -07:00
Gregory Schier
305ed09547 Confirm deletions 2023-03-30 17:09:11 -07:00
Gregory Schier
643356bad3 Dedicated event for model creation 2023-03-30 16:49:49 -07:00
Gregory Schier
e458675627 Unify text selection color 2023-03-30 16:36:24 -07:00
Gregory Schier
91e3853692 Some icon tweaks 2023-03-30 16:29:14 -07:00
Gregory Schier
5f0876a136 Fix strict mode editor blur bug 2023-03-30 10:38:33 -07:00
Gregory Schier
3a38127fb4 Better tauri listeners and stuff 2023-03-30 09:05:54 -07:00
Gregory Schier
f3b6070235 Remove updated_by, remember last location 2023-03-30 08:11:51 -07:00
Gregory Schier
5e6e78eb9e Remove hardcoded window config 2023-03-29 22:16:21 -07:00
Gregory Schier
9b66a1d1a8 Fix build 2023-03-29 22:15:55 -07:00
Gregory Schier
e954d0d7bc Remove unused import 2023-03-29 21:53:49 -07:00
Gregory Schier
dab2df7e79 Better multi-window updates 2023-03-29 21:53:20 -07:00
Gregory Schier
bc40e22008 Fixed key/value stuff 2023-03-29 14:46:36 -07:00
Gregory Schier
eef262c398 Fix bundle parts 2023-03-29 14:00:34 -07:00
Gregory Schier
8eab6e14db Fix(ish) multiwindow updates 2023-03-29 11:15:37 -07:00
Gregory Schier
ded33a110a Obscure text 2023-03-29 10:16:51 -07:00
Gregory Schier
e448a7602a Simple auth schemes 2023-03-29 09:03:38 -07:00
Gregory Schier
4c22215ca5 Good start to multi-window 2023-03-28 18:29:40 -07:00
Gregory Schier
4f501abb72 Focus traps for dialog and dropdown 2023-03-26 23:07:09 -07:00
Gregory Schier
b2dcc38982 Confirmation Dialogs 2023-03-26 12:02:20 -07:00
Gregory Schier
11b719955b Floating sidebar 2023-03-26 10:09:28 -07:00
Gregory Schier
d563ac63db Panel icons 2023-03-25 23:29:04 -07:00
Gregory Schier
6d826064c6 Update dialog 2023-03-25 21:59:18 -07:00
Gregory Schier
d30b9d6518 Optimistically-update key values 2023-03-25 21:54:00 -07:00
Gregory Schier
8da3364d0f More tweaks 2023-03-25 21:40:14 -07:00
Gregory Schier
07c372b7f5 Animate dropdown 2023-03-25 21:36:17 -07:00
Gregory Schier
7e01f38253 Animate sidebar transition 2023-03-25 21:31:52 -07:00
Gregory Schier
ba637009a7 Refactor and improve layout resizing 2023-03-25 21:16:10 -07:00
Gregory Schier
da7388e510 Even better layouts 2023-03-25 18:33:01 -07:00
Gregory Schier
3ec88fc896 Better grid layouts 2023-03-25 18:12:09 -07:00
Gregory Schier
1c9381b2bd Global layout component 2023-03-25 13:26:31 -07:00
Gregory Schier
06349b8d5b Better dropdown separator 2023-03-25 11:06:05 -07:00
Gregory Schier
6dc7dc6ad2 Fix sidebar drag 2023-03-24 08:37:52 -07:00
Gregory Schier
f981a15ec3 Upgrade TYpescript 2023-03-23 15:37:36 -07:00
Gregory Schier
8b648c0301 Fix resize 2023-03-23 07:47:58 -07:00
Gregory Schier
83ce09075b Style tweak 2023-03-21 23:59:09 -07:00
Gregory Schier
168dfb9f6b GraphQL autocomplete and duplicate request 2023-03-21 23:54:45 -07:00
Gregory Schier
9b8961c23d Tweak sidebar drag resizer 2023-03-21 19:36:32 -07:00
Gregory Schier
89bca42ee6 Minor style tweaks 2023-03-21 18:31:05 -07:00
Gregory Schier
07d2a43a17 Pull out resize bar 2023-03-21 16:53:49 -07:00
Gregory Schier
c84f2afd09 Resize titlebar and tweak things 2023-03-21 16:42:52 -07:00
Gregory Schier
df4dbaecc8 Remove icon generation from build script 2023-03-21 14:21:07 -07:00
Gregory Schier
d9bf03cefe query client cache and better body types 2023-03-21 11:38:37 -07:00
Gregory Schier
39223e8d89 Fix workspace deletion 2023-03-21 09:32:15 -07:00
Gregory Schier
67925e18b2 Use proper gray for syntax 2023-03-20 17:15:12 -07:00
Gregory Schier
89ad65513d fix import 2023-03-20 17:13:14 -07:00
Gregory Schier
90166ddfa3 Minor tweaks 2023-03-20 17:12:19 -07:00
Gregory Schier
0981b23faf Fix URL bar spacing 2023-03-20 17:01:29 -07:00
Gregory Schier
664f3b4d87 Better radio dropdown type 2023-03-20 16:54:26 -07:00
Gregory Schier
dc97b91a4e Typesafe routing and CM line height issue 2023-03-20 16:47:36 -07:00
Gregory Schier
d310272d19 Better tab dropdown handling 2023-03-20 14:14:30 -07:00
Gregory Schier
f1be3f01e1 Fix request creation priority 2023-03-20 13:56:03 -07:00
Gregory Schier
c57b6e1d73 Remove log 2023-03-20 13:49:35 -07:00
Gregory Schier
a938dc45f0 Handle "no body" case 2023-03-20 13:49:21 -07:00
Gregory Schier
bb139744a1 Small fix 2023-03-20 13:37:14 -07:00
Gregory Schier
3aa3e09552 Fix pointer window drag 2023-03-20 13:34:49 -07:00
Gregory Schier
74abfd21b8 Fix extra dropdown element 2023-03-20 13:19:23 -07:00
Gregory Schier
e703817ba2 Remove most of Radix UI 2023-03-20 13:16:58 -07:00
Gregory Schier
80dd1e457b Better Header validation 2023-03-20 01:38:05 -07:00
Gregory Schier
ea9f8d3ab2 Tweak sidebar 2023-03-20 01:30:45 -07:00
Gregory Schier
fa222bdf12 Fix pair editor container 2023-03-20 01:18:44 -07:00
Gregory Schier
45b360dabd Fix input thingy 2023-03-20 01:14:13 -07:00
Gregory Schier
5923399359 Container queries! 2023-03-20 01:08:41 -07:00
Gregory Schier
f4600f3e90 Better pair editor delete button 2023-03-20 00:30:42 -07:00
Gregory Schier
f883837685 Pair validation 2023-03-20 00:17:29 -07:00
Gregory Schier
b58bc409f0 Don't send disabled headers 2023-03-20 00:05:19 -07:00
Gregory Schier
e893e539bb Small tweak 2023-03-20 00:04:40 -07:00
Gregory Schier
90294fbb5d Pair checkboxes and fix twig indent 2023-03-20 00:03:33 -07:00
Gregory Schier
ae65f222bc Rewrote twig grammar 2023-03-19 22:12:11 -07:00
Gregory Schier
1b9813fb4c Re-order of pair editor 2023-03-19 13:28:57 -07:00
Gregory Schier
b708b5ae41 Better header editor and added completion data 2023-03-19 11:09:21 -07:00
Gregory Schier
df136fa915 A couple tweaks 2023-03-19 01:01:13 -07:00
Gregory Schier
f8329f5b8d Persist sort priority! 2023-03-19 00:48:09 -07:00
Gregory Schier
21141090de Create new workspace, and more optimizations 2023-03-18 19:36:31 -07:00
Gregory Schier
c0d9740a7d Optimized a few components 2023-03-18 18:49:01 -07:00
Gregory Schier
afcf630443 Fix sidebar drag-n-drop 2023-03-18 18:09:36 -07:00
Gregory Schier
1fe2c9826a Got drag opacity working 2023-03-18 15:06:38 -07:00
Gregory Schier
7272b80a3f Good start to drag-n-drop sidebar! 2023-03-18 14:41:07 -07:00
Gregory Schier
92114b7368 Fix mixed parser 2023-03-17 17:57:43 -07:00
Gregory Schier
f39d3e7eed Dropdown highlight 2023-03-17 17:32:24 -07:00
Gregory Schier
cbe0d27a5e Beginnings of autocomplete for headers 2023-03-17 16:51:20 -07:00
Gregory Schier
cd39699467 Flatten migrations, kvs lib, fix tabs 2023-03-17 08:36:21 -07:00
Gregory Schier
b3ea67aacf Sidebar item dropdown 2023-03-16 15:37:53 -07:00
Gregory Schier
db4ed9797c Sidebar dragging 2023-03-16 14:34:49 -07:00
Gregory Schier
1ea7d7d685 Add devtools toggle hotkey 2023-03-16 11:25:38 -07:00
Gregory Schier
2df725b57a Adjust window sizes 2023-03-16 11:16:23 -07:00
Gregory Schier
74e6648249 Store appearance in k/v 2023-03-16 11:01:30 -07:00
Gregory Schier
1026350d9c Hotkeys and view mode kvs 2023-03-16 09:24:28 -07:00
Gregory Schier
98fb87874d Some fixes 2023-03-15 23:33:46 -07:00
Gregory Schier
41fc3afdc1 Got key values working 2023-03-15 23:24:41 -07:00
Gregory Schier
83dbf46ba4 Fix editor padding 2023-03-15 17:29:35 -07:00
Gregory Schier
0b2e35bdde Minor style updates 2023-03-15 17:25:04 -07:00
Gregory Schier
d90a7331c9 Add stuff to app header 2023-03-15 16:35:19 -07:00
Gregory Schier
264e64a996 Better request delete and formatting 2023-03-15 09:41:38 -07:00
Gregory Schier
8915915c47 Fix graphql and other things 2023-03-15 09:06:56 -07:00
Gregory Schier
951ed787fa Header editor to pair editor 2023-03-15 08:09:45 -07:00
Gregory Schier
64ef6b0c22 Better header editor 2023-03-15 07:54:04 -07:00
Gregory Schier
ef18377b3c Strict mode and tweak layout padding 2023-03-14 20:19:45 -07:00
Gregory Schier
5904b6fded Add GraphQL variables editor 2023-03-14 19:56:02 -07:00
Gregory Schier
f4401e77bb GraphQL query editor transformer works! 2023-03-14 19:08:18 -07:00
Gregory Schier
efa5455a7b Add body type to request and tab dropdown 2023-03-14 11:18:56 -07:00
Gregory Schier
619c8d9e72 Improved header editor 2023-03-14 00:54:41 -07:00
Gregory Schier
bdf89ac288 Fix platform check 2023-03-14 00:15:01 -07:00
Gregory Schier
debd3c8185 Some small changes 2023-03-14 00:08:03 -07:00
Gregory Schier
f81a3ae8e7 Move stuff around 2023-03-13 23:30:14 -07:00
Gregory Schier
7d4e9894c3 Refactor hooks to be easier to use 2023-03-13 23:25:41 -07:00
Gregory Schier
4bf22d8a60 Fix header editor and scroll in general 2023-03-13 19:37:36 -07:00
Gregory Schier
8be4971a23 Lazy load routes 2023-03-13 13:56:13 -07:00
Gregory Schier
359e916b73 Back to React 2023-03-13 09:50:49 -07:00
Gregory Schier
68058f3e41 Move some stuff around 2023-03-13 09:24:38 -07:00
Gregory Schier
0c6fa3e634 Fix URL bar 2023-03-13 00:13:25 -07:00
Gregory Schier
0fa25c6335 Fix ButtonLink and edit request names 2023-03-13 00:11:23 -07:00
Gregory Schier
5684479f1d Remove old rust cache action 2023-03-12 22:48:43 -07:00
Gregory Schier
2d1603601c Better rust cache 2023-03-12 22:47:43 -07:00
Gregory Schier
f5394b2210 Start GraphQL support 2023-03-12 22:43:25 -07:00
Gregory Schier
833db5df06 Fix artifact tag 2023-03-12 21:41:15 -07:00
Gregory Schier
525ac7e980 Remove wasm stuff 2023-03-12 21:25:31 -07:00
Gregory Schier
44a747c80a Use tauri action 2023-03-12 21:13:08 -07:00
Gregory Schier
2056e7f40a Fix traffic lights thingy 2023-03-12 20:47:52 -07:00
Gregory Schier
9b6c1ad364 Cache cargo bin for "install" 2023-03-12 19:10:39 -07:00
Gregory Schier
34987bcacb Refformat 2023-03-12 19:03:27 -07:00
Gregory Schier
b62c11222a Fix artifact upload 2023-03-12 19:01:48 -07:00
Gregory Schier
b3cee3ace3 Fix dev 2023-03-12 18:39:02 -07:00
Gregory Schier
222c054c95 Split out macos deps 2023-03-12 18:36:25 -07:00
Gregory Schier
46f18a2491 Cache workflow 2023-03-12 18:28:14 -07:00
Gregory Schier
f2ca8e2753 Add wasm-pack 2023-03-12 18:19:20 -07:00
Gregory Schier
b0d243c378 Install rsw 2023-03-12 18:14:38 -07:00
Gregory Schier
6161fb86c8 Fix artifact names 2023-03-12 18:13:00 -07:00
Gregory Schier
b09cc91fe5 Fix build command 2023-03-12 18:11:24 -07:00
Gregory Schier
ef1638cbb3 Update secrets context 2023-03-12 18:07:57 -07:00
Gregory Schier
00ef8743f2 Update workflow name 2023-03-12 18:05:45 -07:00
Gregory Schier
68222659e3 Fix workflow 2023-03-12 18:05:13 -07:00
Gregory Schier
69420a4bba Start of auto updates 2023-03-12 18:04:11 -07:00
Gregory Schier
0161bbaeb1 Fix tabbing to tabs 2023-03-11 23:32:39 -08:00
Gregory Schier
948dbfe3cc Fix eslint errors 2023-03-11 23:29:25 -08:00
Gregory Schier
338ba8b189 Got tab content scrolling working 2023-03-11 22:36:13 -08:00
Gregory Schier
ca4655b441 Removed some debug stuff 2023-03-10 10:43:15 -08:00
Gregory Schier
bf37499428 Refactor editor to update better 2023-03-10 10:39:23 -08:00
Gregory Schier
0b94b57e2a Fix headers persistence and better sending 2023-03-09 13:38:17 -08:00
Gregory Schier
fc40aead98 Hook up header editor! 2023-03-09 13:07:13 -08:00
Gregory Schier
7d7f934e6a Fix 2023-03-09 10:58:27 -08:00
Gregory Schier
d5fbf4d622 Fix blur de-select speed 2023-03-09 10:57:34 -08:00
Gregory Schier
e4f6c919dc Fix Codemirror performance!! 2023-03-09 10:50:55 -08:00
Gregory Schier
4d806ff2b1 Switch to Preact!!! 2023-03-09 00:47:25 -08:00
Gregory Schier
bf8f12274f Move some things around 2023-03-08 23:20:15 -08:00
Gregory Schier
f4f438d9fe Better scrollbar color 2023-03-08 19:23:24 -08:00
Gregory Schier
2434f373be Zoom, better sizes, color picker, sidebar footer 2023-03-08 19:22:04 -08:00
Gregory Schier
2bb2061f97 Read-only editor 2023-03-08 16:53:13 -08:00
Gregory Schier
2c011a5c2a More theme tweaks 2023-03-08 16:37:20 -08:00
Gregory Schier
f66b0ccea1 Debounce autocomplete 2023-03-08 11:25:20 -08:00
Gregory Schier
665dd8447d Minor theme updates again 2023-03-08 09:43:35 -08:00
Gregory Schier
1b61ce31e6 Editor tweaks 2023-03-07 23:05:33 -08:00
Gregory Schier
ef4d960698 Remove unneeded space 2023-03-07 22:58:13 -08:00
Gregory Schier
b6d557b632 Fix small view 2023-03-07 22:55:51 -08:00
Gregory Schier
b700bd356c Minor style tweaks 2023-03-07 22:21:58 -08:00
Gregory Schier
620dd7d3ef Lots more theme stuff 2023-03-07 21:52:21 -08:00
Gregory Schier
6575121902 Start of themes 2023-03-07 11:24:38 -08:00
Gregory Schier
7c1755a0dc More subtle layout tweaks 2023-03-06 08:57:57 -08:00
Gregory Schier
8ad301a666 More layout fiddling and error page 2023-03-04 22:26:00 -08:00
Gregory Schier
ae24cd4939 More work on the layout 2023-03-04 21:51:17 -08:00
Gregory Schier
7152e1845e Try new layout and a bunch of editor fixes 2023-03-04 19:06:12 -08:00
Gregory Schier
96c1dd4081 Fix autocomplete inside dialog 2023-03-03 17:03:20 -08:00
Gregory Schier
87c7b3a663 Beginnings of Header Editor 2023-03-03 13:18:57 -08:00
Gregory Schier
c1be46a539 Fix tailwind dark selector 2023-03-03 07:54:19 -08:00
Gregory Schier
4655e0018b Fix content type in URL 2023-03-02 23:17:09 -08:00
Gregory Schier
da5ba2e3be Add Dialog component 2023-03-02 18:46:10 -08:00
Gregory Schier
aaf95f565f More colors 2023-03-02 17:56:53 -08:00
Gregory Schier
f32b984e77 Minor style tweaks 2023-03-02 16:16:41 -08:00
Gregory Schier
548aa4c7cd Improved autocompletion! 2023-03-02 11:14:51 -08:00
Gregory Schier
0ccceaac77 Rename, fix autocomplete and singleline, etc... 2023-03-02 10:42:43 -08:00
Gregory Schier
70f534f1d8 Editor placeholder 2023-03-01 14:22:10 -08:00
Gregory Schier
61fe95b300 Some minor bugs 2023-03-01 14:16:02 -08:00
Gregory Schier
915e0e8613 Fix migrations for build and iframe rendering 2023-03-01 10:31:50 -08:00
Gregory Schier
aace2580da Tweaks 2023-03-01 10:19:21 -08:00
Gregory Schier
3d36905664 Response streaming 2023-03-01 09:05:00 -08:00
Gregory Schier
0d671423da Autocomplete, and more CM stuff! 2023-02-28 22:54:54 -08:00
Gregory Schier
aebfcb9437 Some small tweaks 2023-02-28 17:25:59 -08:00
Gregory Schier
be7ef7beb1 Better editor updating 2023-02-28 12:41:03 -08:00
Gregory Schier
d77ed0c5cc URL highlighting with inline CM 2023-02-28 11:26:26 -08:00
Gregory Schier
e57e7bcec5 Implement request deletion 2023-02-27 15:42:06 -08:00
Gregory Schier
a637842ce4 Tauri events for request model updates 2023-02-27 13:28:50 -08:00
Gregory Schier
fc54ec49af Split request upsert command 2023-02-27 10:00:57 -08:00
Gregory Schier
5c43d8510a Add toggle for pretty view 2023-02-27 09:08:48 -08:00
Gregory Schier
83f84ded8d Small tweaks 2023-02-26 15:25:55 -08:00
Gregory Schier
5658da34a2 Add variable highlighting widgets 2023-02-26 15:06:14 -08:00
Gregory Schier
38e8ef6535 Dropdown scrolling 2023-02-25 23:33:07 -08:00
Gregory Schier
8c89b06238 Show response body size 2023-02-25 23:08:19 -08:00
Gregory Schier
d85c021305 A bunch more small things 2023-02-25 23:04:31 -08:00
Gregory Schier
83bb18df03 Added react-router 2023-02-25 18:04:14 -08:00
Gregory Schier
93105a3e89 Migrations and initial data stuff 2023-02-25 16:39:18 -08:00
Gregory Schier
ba3b899115 Minor tweaks 2023-02-24 17:01:48 -08:00
Gregory Schier
fcfbc1d1da Dummy requests in sidebar 2023-02-24 16:46:56 -08:00
Gregory Schier
72486b448c Codemirror initial value support 2023-02-24 16:43:47 -08:00
Gregory Schier
7dea1b7870 Send request body 2023-02-24 16:09:19 -08:00
Gregory Schier
4de2c496c9 Vendor basicSetup 2023-02-24 14:51:56 -08:00
Gregory Schier
9e1393a392 Additional methods and tweaks 2023-02-24 14:10:25 -08:00
Gregory Schier
0901690ed6 Focus states 2023-02-24 12:35:13 -08:00
Gregory Schier
95303648cc Hook up theme and clear responses 2023-02-24 12:13:30 -08:00
Gregory Schier
1dbb08c045 SQLite store in proper dir 2023-02-22 20:18:14 -08:00
Gregory Schier
00a7d9a180 Started on grid layout 2023-02-22 19:44:44 -08:00
Gregory Schier
6c549dc086 Save responses in DB 2023-02-22 18:53:44 -08:00
Gregory Schier
dc368e326a Better URL bar 2023-02-22 16:15:25 -08:00
Gregory Schier
e42188a627 Cleaner URL bar and some improvements 2023-02-22 15:58:04 -08:00
Gregory Schier
7a6a337eff Refactor classname usage 2023-02-21 18:03:57 -08:00
Gregory Schier
3907344884 Some minor tweaks 2023-02-21 17:56:48 -08:00
897 changed files with 32547 additions and 233297 deletions

View File

@@ -1,6 +1,5 @@
node_modules/
dist/
.eslintrc.cjs
.prettierrc.cjs
src-web/postcss.config.cjs
src-web/vite.config.ts
.eslintrc.cjs
env.d.ts

View File

@@ -1,49 +1,37 @@
module.exports = {
extends: [
'eslint:recommended',
'plugin:react/recommended',
'plugin:react-hooks/recommended',
'plugin:import/recommended',
'plugin:jsx-a11y/recommended',
'plugin:@typescript-eslint/recommended',
'eslint-config-prettier',
"eslint:recommended",
"plugin:react/recommended",
"plugin:react-hooks/recommended",
"plugin:import/recommended",
"plugin:jsx-a11y/recommended",
"plugin:@typescript-eslint/recommended",
"eslint-config-prettier"
],
plugins: ['react-refresh'],
parser: '@typescript-eslint/parser',
parser: "@typescript-eslint/parser",
parserOptions: {
project: ['./tsconfig.json'],
project: ["./tsconfig.json"]
},
ignorePatterns: [
'scripts/**/*',
'packages/plugin-runtime/**/*',
'packages/plugin-runtime-types/**/*',
'src-tauri/**/*',
'src-web/tailwind.config.cjs',
'src-web/vite.config.ts',
],
ignorePatterns: ["src-tauri/**/*", "plugins/**/*"],
settings: {
react: {
version: 'detect',
version: "detect"
},
'import/resolver': {
"import/resolver": {
node: {
paths: ['src-web'],
extensions: ['.ts', '.tsx'],
},
},
paths: ["src-web"],
extensions: [".ts", ".tsx"]
}
}
},
rules: {
'react-refresh/only-export-components': 'error',
'jsx-a11y/no-autofocus': 'off',
'react/react-in-jsx-scope': 'off',
'import/no-unresolved': 'off',
'@typescript-eslint/consistent-type-imports': [
'error',
{
prefer: 'type-imports',
disallowTypeAnnotations: true,
fixStyle: 'separate-type-imports',
},
],
},
"jsx-a11y/no-autofocus": "off",
"react/react-in-jsx-scope": "off",
"import/no-unresolved": "off",
"@typescript-eslint/consistent-type-imports": ["error", {
prefer: "type-imports",
disallowTypeAnnotations: true,
fixStyle: "separate-type-imports"
}]
}
};

2
.gitattributes vendored
View File

@@ -1,2 +0,0 @@
src-tauri/vendored/**/* linguist-generated=true
src-tauri/gen/schemas/**/* linguist-generated=true

15
.github/FUNDING.yml vendored
View File

@@ -1,15 +0,0 @@
# These are supported funding model platforms
github: gschier
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
thanks_dev: # Replace with a single thanks.dev username
custom: https://yaak.app/pricing

View File

@@ -1,38 +0,0 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Bugs, Feedback, Feature Requests, and Questions
url: https://feedback.yaak.app
about: "Please report to Yaak's public feedback board. Issues will be created and linked here when applicable."

72
.github/workflows/artifacts.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
name: Generate Artifacts
on:
push:
tags: [ v* ]
permissions: write-all
jobs:
build-artifacts:
name: Build
strategy:
fail-fast: false
matrix:
include:
- os: macos-latest
target: aarch64-apple-darwin
- os: macos-latest
target: x86_64-apple-darwin
- os: windows-latest
target: x86_64-pc-windows-msvc
- os: ubuntu-20.04
target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v3
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- name: Cache Rust
uses: actions/cache@v2
with:
path: |
~/.cargo/registry
~/.cargo/git
./src-tauri/target
key: ${{ runner.os }}-cargo-${{ hashFiles('src-tauri/Cargo.lock') }}
- uses: actions/setup-node@v3
with:
node-version: 20
cache: 'npm'
- name: install dependencies (ubuntu only)
if: matrix.os == 'ubuntu-20.04'
run: |
sudo apt-get update
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libappindicator3-dev librsvg2-dev patchelf
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
# Pin dev version to get non-default targets
# https://github.com/tauri-apps/tauri-action/issues/356
- uses: tauri-apps/tauri-action@dev
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }}
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
with:
tagName: 'v__VERSION__'
releaseName: 'Release __VERSION__'
releaseBody: 'https://yaak.app/changelog/__VERSION__'
releaseDraft: true
prerelease: false
args: '--target ${{ matrix.target }}'

View File

@@ -1,18 +0,0 @@
on:
pull_request:
branches: [develop]
name: CI (JS)
jobs:
test:
name: Lint/Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run lint
- run: npm test

View File

@@ -1,36 +0,0 @@
on:
pull_request:
branches: [develop]
paths:
- src-tauri/**
- .github/workflows/**
name: CI (Rust)
defaults:
run:
working-directory: src-tauri
jobs:
test:
name: Check/Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev
- uses: dtolnay/rust-toolchain@stable
- uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- run: cargo check --all
- run: cargo test --all

View File

@@ -1,125 +0,0 @@
name: Generate Artifacts
on:
push:
tags: [ v* ]
env:
YAAK_PLUGINS_DIR: checkout/plugins
jobs:
build-artifacts:
permissions:
contents: write
name: Build
strategy:
fail-fast: false
matrix:
include:
- platform: 'macos-latest' # for Arm-based Macs (M1 and above).
args: '--target aarch64-apple-darwin'
yaak_arch: 'arm64'
- platform: 'macos-latest' # for Intel-based Macs.
args: '--target x86_64-apple-darwin'
yaak_arch: 'x64'
- platform: 'ubuntu-22.04'
args: ''
yaak_arch: 'x64'
- platform: 'windows-latest'
args: ''
yaak_arch: 'x64'
runs-on: ${{ matrix.platform }}
timeout-minutes: 40
steps:
- name: Checkout yaakapp/app
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: 22
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
with:
# Those targets are only used on macos runners so it's in an `if` to slightly speed up windows and linux builds.
targets: ${{ matrix.platform == 'macos-latest' && 'aarch64-apple-darwin,x86_64-apple-darwin' || '' }}
- uses: actions/cache@v3
continue-on-error: false
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
src-tauri/target/
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
restore-keys: ${{ runner.os }}-cargo-
- name: install dependencies (ubuntu only)
if: matrix.platform == 'ubuntu-22.04' # This must match the platform value defined above.
run: |
sudo apt-get update
sudo apt-get install -y libwebkit2gtk-4.1-dev libappindicator3-dev librsvg2-dev patchelf
- name: install dependencies (windows only)
if: matrix.platform == 'windows-latest'
run: cargo install --force trusted-signing-cli --version 0.5.0
- name: Install NPM Dependencies
run: |
npm ci
npm install @yaakapp/cli
- name: Install Protoc for plugin-runtime
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: Run JS build
run: npm run build
- name: Run lint
run: npm run lint
- name: Checkout yaakapp/plugins
uses: actions/checkout@v4
with:
repository: yaakapp/plugins
path: ${{ env.YAAK_PLUGINS_DIR }}
- name: Set version
run: npm run replace-version
env:
YAAK_VERSION: ${{ github.ref_name }}
- uses: tauri-apps/tauri-action@v0
env:
YAAK_PLUGINS_DIR: ${{ env.YAAK_PLUGINS_DIR }}
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
ENABLE_CODE_SIGNING: ${{ secrets.APPLE_CERTIFICATE }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
# Apple signing stuff
APPLE_CERTIFICATE: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE }}
APPLE_CERTIFICATE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_CERTIFICATE_PASSWORD }}
APPLE_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_PASSWORD }}
APPLE_SIGNING_IDENTITY: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_SIGNING_IDENTITY }}
APPLE_TEAM_ID: ${{ matrix.platform == 'macos-latest' && secrets.APPLE_TEAM_ID }}
# Windows signing stuff
AZURE_CLIENT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_CLIENT_SECRET }}
AZURE_TENANT_ID: ${{ matrix.platform == 'windows-latest' && secrets.AZURE_TENANT_ID }}
with:
tagName: 'v__VERSION__'
releaseName: 'Release __VERSION__'
releaseBody: '[Changelog __VERSION__](https://yaak.app/blog/__VERSION__)'
releaseDraft: true
prerelease: false
args: ${{ matrix.args }}

5
.gitignore vendored
View File

@@ -26,8 +26,3 @@ dist-ssr
*.sqlite
*.sqlite-*
.cargo
.tmp
tmp

1
.husky/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
_

4
.husky/pre-commit Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged

8
.prettierrc.cjs Normal file
View File

@@ -0,0 +1,8 @@
module.exports = {
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"printWidth": 100,
"bracketSpacing": true
}

View File

@@ -1,8 +0,0 @@
export default {
"trailingComma": "all",
"tabWidth": 2,
"semi": true,
"singleQuote": true,
"printWidth": 100,
"bracketSpacing": true
}

View File

@@ -0,0 +1,20 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Build Desktop" type="ShConfigurationType">
<option name="SCRIPT_TEXT" value="npm run tauri build -- --target universal-apple-darwin" />
<option name="INDEPENDENT_SCRIPT_PATH" value="true" />
<option name="SCRIPT_PATH" value="" />
<option name="SCRIPT_OPTIONS" value="" />
<option name="INDEPENDENT_SCRIPT_WORKING_DIRECTORY" value="true" />
<option name="SCRIPT_WORKING_DIRECTORY" value="$PROJECT_DIR$" />
<option name="INDEPENDENT_INTERPRETER_PATH" value="true" />
<option name="INTERPRETER_PATH" value="/bin/zsh" />
<option name="INTERPRETER_OPTIONS" value="" />
<option name="EXECUTE_IN_TERMINAL" value="true" />
<option name="EXECUTE_SCRIPT_FILE" value="false" />
<envs>
<env name="TAURI_KEY_PASSWORD" value="fishhook-upstream-wash-assured" />
<env name="TAURI_PRIVATE_KEY" value="dW50cnVzdGVkIGNvbW1lbnQ6IHJzaWduIGVuY3J5cHRlZCBzZWNyZXQga2V5ClJXUlRZMEl5OGxWaytTa3dIa2xXVUltQzRGUXIzd2lYQ2NpV0ZhQURSbWJWZ1NrK0tnY0FBQkFBQUFBQUFBQUFBQUlBQUFBQUV2M1VKdVRyVHpHSzhQdGc2ZVFtOVNsMU5tNEVSN280cFNrbXhncW9tdjNXaFJZUTJqUzQ5Q01zWTJWRVhaY1pGNHNjR1NFR3JmcWFRN09NdWdGMXpZVXhzejR4V3lDV1JpZHlnbW5LNS9vMFFtRlZjbUl4YjZSNzhlMmk3ait5SExYcG5QZUkxOFE9Cg==" />
</envs>
<method v="2" />
</configuration>
</component>

13
.run/Dev Desktop.run.xml Normal file
View File

@@ -0,0 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Dev Desktop" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs>
</envs>
<method v="2" />
</configuration>
</component>

5
.sqllsrc.json Normal file
View File

@@ -0,0 +1,5 @@
{
"name": "yaak-dev",
"adapter": "sqlite3",
"filename": "src-tauri/db.sqlite"
}

1
.tauriignore Normal file
View File

@@ -0,0 +1 @@
plugins

View File

@@ -1,69 +0,0 @@
# Developer Setup
Yaak is a combined Node.js and Rust monorepo. It is a [Tauri](https://tauri.app) project, so
uses Rust and HTML/CSS/JS for the main application but there is also a plugin system powered
by a Node.js sidecar that communicates to the app over gRPC.
Because of the moving parts, there are a few setup steps required before development can
begin.
## Prerequisites
Make sure you have the following tools installed:
- [Node.js](https://nodejs.org/en/download/package-manager)
- [Rust](https://www.rust-lang.org/tools/install)
Check the installations with the following commands:
```shell
node -v
npm -v
rustc --version
```
Install the NPM dependencies:
```shell
npm install
```
Run the `bootstrap` command to do some initial setup:
```shell
npm run bootstrap
```
_NOTE: Run with `YAAK_PLUGINS_DIR=<Path to yaakapp/plugins>` to re-build bundled plugins_
## Run the App
After bootstrapping, start the app in development mode:
```shell
npm start
```
_NOTE: If working on bundled plugins, run with `YAAK_PLUGINS_DIR=<Path to yaakapp/plugins>`_
## SQLite Migrations
New migrations can be created from the `src-tauri/` directory:
```shell
cd src-tauri
sqlx migrate add migration-name
```
Run the app to apply the migrations.
If nothing happens, try `cargo clean` and run the app again.
_Note: Development builds use a separate database location from production builds._
## Lezer Grammer Generation
```sh
# Example
lezer-generator components/core/Editor/<LANG>/<LANG>.grammar > components/core/Editor/<LANG>/<LANG>.ts
```

21
LICENSE
View File

@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2024 Yaak
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

13
Makefile Normal file
View File

@@ -0,0 +1,13 @@
.PHONY: sqlx-prepare, dev, migrate, build
sqlx-prepare:
cd src-tauri && cargo sqlx prepare --database-url 'sqlite://db.sqlite'
dev:
npm run tauri-dev
migrate:
cd src-tauri && cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
build:
./node_modules/.bin/tauri build

View File

@@ -1,34 +1,16 @@
# Yaak API Client
# Yaak Network Toolkit
Yaak is a desktop API client for interacting with REST, GraphQL, Server Sent Events (SSE), WebSocket, and gRPC
APIs. It's built using [Tauri](https://tauri.app), Rust, and ReactJS.
The most fun you'll ever have working with APIs.
![366149288-f18e963f-0b68-4ecb-b8b8-cb71aa9aec02](https://github.com/user-attachments/assets/ca83b7ad-5708-411b-8faf-e36b365841a4)
## Common Commands
## Contribution Policy
```sh
# Start dev app
npm run tauri-dev
Yaak is open source, but only accepting contributions for bug fixes. To get started,
visit [`DEVELOPMENT.md`](DEVELOPMENT.md) for tips on setting up your environment.
## Feature Overview
- 🪂 Import data from Postman, Insomnia, OpenAPI, Swagger, or Curl.<br/>
- 📤 Send requests via REST, GraphQL, Server Sent Events (SSE), WebSockets, or gRPC.<br/>
- 🔐 Automatically authorize requests with OAuth 2.0, JWT tokens, Basic Auth, and more.<br/>
- 🔎 Filter response bodies using JSONPath or XPath queries.<br/>
- ⛓️ Chain together multiple requests to dynamically reference values.<br/>
- 📂 Organize requests into workspaces and nested folders.<br/>
- 🧮 Use environment variables to easily switch between Prod and Dev.<br/>
- 🛡️ Secure arbitrary text values with end-to-end encryption<br/>
- 🏷️ Send dynamic values like UUIDs or timestamps using template tags.<br/>
- 🎨 Choose from many of the included themes, or make your own.<br/>
- 💽 Mirror workspace data to a directory for integration with Git or Dropbox.<br/>
- 📜 View response history for each request.<br/>
- 🔌 Create your own plugins for authentication, template tags, and more!<br/>
- 🛜 Configure a proxy to access firewall-blocked APIs
## Useful Resources
- [Feedback and Bug Reports](https://feedback.yaak.app)
- [Documentation](https://feedback.yaak.app/help)
- [Yaak vs Postman](https://yaak.app/blog/postman-alternative)
# Migration commands
cd src-tauri
cargo sqlx migrate add ${MIGRATION_NAME}
cargo sqlx migrate run --database-url 'sqlite://db.sqlite?mode=rw'
cargo sqlx prepare --database-url 'sqlite://db.sqlite'
```

BIN
design/Icons.afdesign Normal file
View File

Binary file not shown.

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

Before

Width:  |  Height:  |  Size: 356 KiB

After

Width:  |  Height:  |  Size: 356 KiB

BIN
design/logo.afdesign Normal file
View File

Binary file not shown.

View File

@@ -1,33 +1,31 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Yaak App</title>
<!-- <script src="http://localhost:8097"></script>-->
<!-- <script src="http://localhost:8097"></script>-->
<!-- Certain elements like webview (and maybe <select>?) will use background
color depending on document background color-->
<style>
html, body {
background-color: white;
}
@media (prefers-color-scheme: dark) {
html, body {
background-color: #1b1a29;
background-color: white;
}
@media (prefers-color-scheme: dark) {
html, body {
background-color: black;
}
}
}
</style>
</head>
<body class="text-base">
<body>
<div id="root"></div>
<div id="cm-portal" class="cm-portal"></div>
<div id="react-portal"></div>
<div id="radix-portal" class="cm-portal"></div>
<script type="module" src="/theme.ts"></script>
<script type="module" src="/font-size.ts"></script>
<script type="module" src="/main.tsx"></script>
<script type="module" src="/src-web/main.tsx"></script>
</body>
</html>

12437
package-lock.json generated
View File

File diff suppressed because it is too large Load Diff

View File

@@ -2,57 +2,105 @@
"name": "yaak-app",
"private": true,
"version": "0.0.0",
"repository": {
"type": "git",
"url": "git+https://github.com/mountain-loop/yaak.git"
},
"workspaces": [
"packages/plugin-runtime",
"packages/plugin-runtime-types",
"packages/common-lib",
"src-tauri/yaak-crypto",
"src-tauri/yaak-git",
"src-tauri/yaak-license",
"src-tauri/yaak-mac-window",
"src-tauri/yaak-models",
"src-tauri/yaak-plugins",
"src-tauri/yaak-sse",
"src-tauri/yaak-sync",
"src-tauri/yaak-templates",
"src-tauri/yaak-ws",
"src-web"
],
"type": "module",
"scripts": {
"start": "npm run app-dev",
"app-build": "tauri build",
"app-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
"build": "npm run --workspaces --if-present build",
"bootstrap": "run-p bootstrap:* && npm run --workspaces --if-present bootstrap",
"bootstrap:vendor-node": "node scripts/vendor-node.cjs",
"bootstrap:vendor-plugins": "node scripts/vendor-plugins.cjs",
"bootstrap:vendor-protoc": "node scripts/vendor-protoc.cjs",
"lint": "npm run --workspaces --if-present lint",
"replace-version": "node scripts/replace-version.cjs",
"start": "npm run build:plugins && npm run tauri-dev",
"tauri-dev": "tauri dev --no-watch --config ./src-tauri/tauri-dev.conf.json",
"tauri-build": "tauri build",
"tauri": "tauri",
"tauri-before-build": "npm run bootstrap && npm run --workspaces --if-present build",
"tauri-before-dev": "npm run --workspaces --if-present dev"
"build": "npm run build:frontend",
"dev": "vite dev",
"lint": "tsc && eslint . --ext .ts,.tsx",
"build:icon:release": "tauri icon design/icon.png --output ./src-tauri/icons/release",
"build:icon:dev": "tauri icon design/icon-dev.png --output ./src-tauri/icons/dev",
"build:frontend": "vite build",
"build:plugins": "run-p build:plugin:*",
"build:plugin:importer-insomnia": "cd plugins/importer-insomnia && vite build --emptyOutDir",
"build:plugin:importer-postman": "cd plugins/importer-postman && vite build --emptyOutDir",
"build:plugin:importer-yaak": "cd plugins/importer-yaak && vite build --emptyOutDir",
"build:plugin:filter-jsonpath": "cd plugins/filter-jsonpath && vite build --emptyOutDir",
"build:plugin:filter-xpath": "cd plugins/filter-xpath && vite build --emptyOutDir",
"test": "vitest",
"coverage": "vitest run --coverage",
"prepare": "husky install"
},
"dependencies": {
"jotai": "^2.12.2"
"@codemirror/commands": "^6.2.1",
"@codemirror/lang-javascript": "^6.1.4",
"@codemirror/lang-json": "^6.0.1",
"@codemirror/lang-xml": "^6.0.2",
"@codemirror/language": "^6.6.0",
"@codemirror/search": "^6.2.3",
"@lezer/generator": "^1.2.2",
"@lezer/highlight": "^1.1.3",
"@lezer/lr": "^1.3.3",
"@react-hook/resize-observer": "^1.2.6",
"@tailwindcss/container-queries": "^0.1.0",
"@tanstack/query-sync-storage-persister": "^4.27.1",
"@tanstack/react-query": "^4.28.0",
"@tanstack/react-query-devtools": "^4.28.0",
"@tanstack/react-query-persist-client": "^4.28.0",
"@tauri-apps/api": "^1.5.3",
"buffer": "^6.0.3",
"classnames": "^2.3.2",
"cm6-graphql": "^0.0.9",
"codemirror": "^6.0.1",
"codemirror-json-schema": "^0.6.1",
"date-fns": "^3.3.1",
"focus-trap-react": "^10.1.1",
"format-graphql": "^1.4.0",
"framer-motion": "^9.0.4",
"lucide-react": "^0.309.0",
"papaparse": "^5.4.1",
"parse-color": "^1.0.0",
"react": "^18.2.0",
"react-dnd": "^16.0.1",
"react-dnd-html5-backend": "^16.0.1",
"react-dom": "^18.2.0",
"react-helmet-async": "^1.3.0",
"react-router-dom": "^6.8.1",
"react-use": "^17.4.0",
"slugify": "^1.6.6",
"tauri-plugin-log-api": "github:tauri-apps/tauri-plugin-log#v1",
"uuid": "^9.0.0",
"xml-formatter": "^3.6.2"
},
"devDependencies": {
"@tauri-apps/cli": "^2.4.1",
"@typescript-eslint/eslint-plugin": "^8.27.0",
"@typescript-eslint/parser": "^8.27.0",
"eslint": "^8",
"eslint-config-prettier": "^8",
"eslint-plugin-import": "^2.31.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-react-hooks": "^5.1.0",
"nodejs-file-downloader": "^4.13.0",
"@tailwindcss/nesting": "^0.0.0-insiders.565cd3e",
"@tauri-apps/cli": "^1.5.10",
"@types/node": "^18.7.10",
"@types/papaparse": "^5.3.7",
"@types/parse-color": "^1.0.1",
"@types/parse-json": "^4.0.0",
"@types/react": "^18.0.31",
"@types/react-dom": "^18.0.11",
"@types/uuid": "^9.0.1",
"@typescript-eslint/eslint-plugin": "^7.0.2",
"@typescript-eslint/parser": "^7.0.2",
"@vitejs/plugin-react": "^4.2.1",
"autoprefixer": "^10.4.13",
"eslint": "^8.34.0",
"eslint-config-prettier": "^8.6.0",
"eslint-plugin-import": "^2.27.5",
"eslint-plugin-jsx-a11y": "^6.7.1",
"eslint-plugin-react": "^7.32.2",
"eslint-plugin-react-hooks": "^4.6.0",
"husky": "^8.0.3",
"lint-staged": "^15.0.2",
"npm-run-all": "^4.1.5",
"prettier": "^3.4.2",
"typescript": "^5.8.2"
"postcss": "^8.4.21",
"postcss-nesting": "^11.2.1",
"prettier": "^2.8.4",
"react-devtools": "^4.27.2",
"tailwindcss": "^3.2.7",
"typescript": "^5.3.3",
"vite": "^5.1.1",
"vite-plugin-svgr": "^4.2.0",
"vite-plugin-top-level-await": "^1.4.1",
"vitest": "^1.3.0"
},
"lint-staged": {
"*.{ts,tsx}": "eslint --cache --fix",
"*.{js,css,md}": "prettier --write"
}
}

View File

@@ -1,20 +0,0 @@
export function formatSize(bytes: number): string {
let num;
let unit;
if (bytes > 1000 * 1000 * 1000) {
num = bytes / 1000 / 1000 / 1000;
unit = 'GB';
} else if (bytes > 1000 * 1000) {
num = bytes / 1000 / 1000;
unit = 'MB';
} else if (bytes > 1000) {
num = bytes / 1000;
unit = 'KB';
} else {
num = bytes;
unit = 'B';
}
return `${Math.round(num * 10) / 10} ${unit}`;
}

View File

@@ -1 +0,0 @@
export * from './debounce';

View File

@@ -1,6 +0,0 @@
{
"name": "@yaakapp-internal/lib",
"private": true,
"version": "1.0.0",
"main": "index.ts"
}

View File

@@ -1,2 +0,0 @@
lib
node_modules

View File

@@ -1,47 +0,0 @@
{
"name": "@yaakapp/api",
"version": "0.1.17",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@yaakapp/api",
"version": "0.1.17",
"dependencies": {
"@types/node": "^22.5.4"
},
"devDependencies": {
"typescript": "^5.6.2"
}
},
"node_modules/@types/node": {
"version": "22.5.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz",
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
"license": "MIT",
"dependencies": {
"undici-types": "~6.19.2"
}
},
"node_modules/typescript": {
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"dev": true,
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/undici-types": {
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"license": "MIT"
}
}
}

View File

@@ -1,25 +0,0 @@
{
"name": "@yaakapp/api",
"version": "0.5.3",
"main": "lib/index.js",
"typings": "./lib/index.d.ts",
"files": [
"lib/**/*"
],
"scripts": {
"bootstrap": "npm run build",
"build": "run-s build:copy-types build:tsc",
"build:tsc": "tsc",
"build:copy-types": "run-p build:copy-types:*",
"build:copy-types:root": "cpy --flat ../../src-tauri/yaak-plugins/bindings/*.ts ./src/bindings",
"build:copy-types:next": "cpy --flat ../../src-tauri/yaak-plugins/bindings/serde_json/*.ts ./src/bindings/serde_json",
"publish": "npm publish",
"prepublishOnly": "npm run build"
},
"dependencies": {
"@types/node": "^22.5.4"
},
"devDependencies": {
"cpy-cli": "^5.0.0"
}
}

View File

@@ -1,411 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { Environment } from "./gen_models.js";
import type { Folder } from "./gen_models.js";
import type { GrpcRequest } from "./gen_models.js";
import type { HttpRequest } from "./gen_models.js";
import type { HttpResponse } from "./gen_models.js";
import type { JsonValue } from "./serde_json/JsonValue.js";
import type { WebsocketRequest } from "./gen_models.js";
import type { Workspace } from "./gen_models.js";
export type BootRequest = { dir: string, watch: boolean, };
export type BootResponse = { name: string, version: string, };
export type CallHttpAuthenticationActionArgs = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
export type CallHttpAuthenticationActionRequest = { index: number, pluginRefId: string, args: CallHttpAuthenticationActionArgs, };
export type CallHttpAuthenticationRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, method: string, url: string, headers: Array<HttpHeader>, };
export type CallHttpAuthenticationResponse = {
/**
* HTTP headers to add to the request. Existing headers will be replaced, while
* new headers will be added.
*/
setHeaders: Array<HttpHeader>, };
export type CallHttpRequestActionArgs = { httpRequest: HttpRequest, };
export type CallHttpRequestActionRequest = { index: number, pluginRefId: string, args: CallHttpRequestActionArgs, };
export type CallTemplateFunctionArgs = { purpose: RenderPurpose, values: { [key in string]?: string }, };
export type CallTemplateFunctionRequest = { name: string, args: CallTemplateFunctionArgs, };
export type CallTemplateFunctionResponse = { value: string | null, };
export type CloseWindowRequest = { label: string, };
export type Color = "primary" | "secondary" | "info" | "success" | "notice" | "warning" | "danger";
export type CompletionOptionType = "constant" | "variable";
export type Content = { "type": "text", content: string, } | { "type": "markdown", content: string, };
export type CopyTextRequest = { text: string, };
export type DeleteKeyValueRequest = { key: string, };
export type DeleteKeyValueResponse = { deleted: boolean, };
export type EditorLanguage = "text" | "javascript" | "json" | "html" | "xml" | "graphql" | "markdown";
export type EmptyPayload = {};
export type ErrorResponse = { error: string, };
export type ExportHttpRequestRequest = { httpRequest: HttpRequest, };
export type ExportHttpRequestResponse = { content: string, };
export type FileFilter = { name: string,
/**
* File extensions to require
*/
extensions: Array<string>, };
export type FilterRequest = { content: string, filter: string, };
export type FilterResponse = { content: string, };
export type FindHttpResponsesRequest = { requestId: string, limit?: number, };
export type FindHttpResponsesResponse = { httpResponses: Array<HttpResponse>, };
export type FormInput = { "type": "text" } & FormInputText | { "type": "editor" } & FormInputEditor | { "type": "select" } & FormInputSelect | { "type": "checkbox" } & FormInputCheckbox | { "type": "file" } & FormInputFile | { "type": "http_request" } & FormInputHttpRequest | { "type": "accordion" } & FormInputAccordion | { "type": "banner" } & FormInputBanner | { "type": "markdown" } & FormInputMarkdown;
export type FormInputAccordion = { label: string, inputs?: Array<FormInput>, hidden?: boolean, };
export type FormInputBanner = { inputs?: Array<FormInput>, hidden?: boolean, color?: Color, };
export type FormInputBase = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type FormInputCheckbox = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type FormInputEditor = {
/**
* Placeholder for the text input
*/
placeholder?: string | null,
/**
* Don't show the editor gutter (line numbers, folds, etc.)
*/
hideGutter?: boolean,
/**
* Language for syntax highlighting
*/
language?: EditorLanguage, readOnly?: boolean, completionOptions?: Array<GenericCompletionOption>,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type FormInputFile = {
/**
* The title of the file selection window
*/
title: string,
/**
* Allow selecting multiple files
*/
multiple?: boolean, directory?: boolean, defaultPath?: string, filters?: Array<FileFilter>,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type FormInputHttpRequest = {
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type FormInputMarkdown = { content: string, hidden?: boolean, };
export type FormInputSelect = {
/**
* The options that will be available in the select input
*/
options: Array<FormInputSelectOption>,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type FormInputSelectOption = { label: string, value: string, };
export type FormInputText = {
/**
* Placeholder for the text input
*/
placeholder?: string | null,
/**
* Placeholder for the text input
*/
password?: boolean,
/**
* Whether to allow newlines in the input, like a <textarea/>
*/
multiLine?: boolean, completionOptions?: Array<GenericCompletionOption>,
/**
* The name of the input. The value will be stored at this object attribute in the resulting data
*/
name: string,
/**
* Whether this input is visible for the given configuration. Use this to
* make branching forms.
*/
hidden?: boolean,
/**
* Whether the user must fill in the argument
*/
optional?: boolean,
/**
* The label of the input
*/
label?: string,
/**
* Visually hide the label of the input
*/
hideLabel?: boolean,
/**
* The default value
*/
defaultValue?: string, disabled?: boolean, };
export type GenericCompletionOption = { label: string, detail?: string, info?: string, type?: CompletionOptionType, boost?: number, };
export type GetHttpAuthenticationConfigRequest = { contextId: string, values: { [key in string]?: JsonPrimitive }, };
export type GetHttpAuthenticationConfigResponse = { args: Array<FormInput>, pluginRefId: string, actions?: Array<HttpAuthenticationAction>, };
export type GetHttpAuthenticationSummaryResponse = { name: string, label: string, shortLabel: string, };
export type GetHttpRequestActionsRequest = Record<string, never>;
export type GetHttpRequestActionsResponse = { actions: Array<HttpRequestAction>, pluginRefId: string, };
export type GetHttpRequestByIdRequest = { id: string, };
export type GetHttpRequestByIdResponse = { httpRequest: HttpRequest | null, };
export type GetKeyValueRequest = { key: string, };
export type GetKeyValueResponse = { value?: string, };
export type GetTemplateFunctionsResponse = { functions: Array<TemplateFunction>, pluginRefId: string, };
export type HttpAuthenticationAction = { label: string, icon?: Icon, };
export type HttpHeader = { name: string, value: string, };
export type HttpRequestAction = { label: string, icon?: Icon, };
export type Icon = "alert_triangle" | "check" | "check_circle" | "chevron_down" | "copy" | "info" | "pin" | "search" | "trash" | "_unknown";
export type ImportRequest = { content: string, };
export type ImportResources = { workspaces: Array<Workspace>, environments: Array<Environment>, folders: Array<Folder>, httpRequests: Array<HttpRequest>, grpcRequests: Array<GrpcRequest>, websocketRequests: Array<WebsocketRequest>, };
export type ImportResponse = { resources: ImportResources, };
export type InternalEvent = { id: string, pluginRefId: string, pluginName: string, replyId: string | null, windowContext: PluginWindowContext, payload: InternalEventPayload, };
export type InternalEventPayload = { "type": "boot_request" } & BootRequest | { "type": "boot_response" } & BootResponse | { "type": "reload_request" } & EmptyPayload | { "type": "reload_response" } & EmptyPayload | { "type": "terminate_request" } | { "type": "terminate_response" } | { "type": "import_request" } & ImportRequest | { "type": "import_response" } & ImportResponse | { "type": "filter_request" } & FilterRequest | { "type": "filter_response" } & FilterResponse | { "type": "export_http_request_request" } & ExportHttpRequestRequest | { "type": "export_http_request_response" } & ExportHttpRequestResponse | { "type": "send_http_request_request" } & SendHttpRequestRequest | { "type": "send_http_request_response" } & SendHttpRequestResponse | { "type": "get_http_request_actions_request" } & EmptyPayload | { "type": "get_http_request_actions_response" } & GetHttpRequestActionsResponse | { "type": "call_http_request_action_request" } & CallHttpRequestActionRequest | { "type": "get_template_functions_request" } | { "type": "get_template_functions_response" } & GetTemplateFunctionsResponse | { "type": "call_template_function_request" } & CallTemplateFunctionRequest | { "type": "call_template_function_response" } & CallTemplateFunctionResponse | { "type": "get_http_authentication_summary_request" } & EmptyPayload | { "type": "get_http_authentication_summary_response" } & GetHttpAuthenticationSummaryResponse | { "type": "get_http_authentication_config_request" } & GetHttpAuthenticationConfigRequest | { "type": "get_http_authentication_config_response" } & GetHttpAuthenticationConfigResponse | { "type": "call_http_authentication_request" } & CallHttpAuthenticationRequest | { "type": "call_http_authentication_response" } & CallHttpAuthenticationResponse | { "type": "call_http_authentication_action_request" } & CallHttpAuthenticationActionRequest | { "type": "call_http_authentication_action_response" } & EmptyPayload | { "type": "copy_text_request" } & CopyTextRequest | { "type": "copy_text_response" } & EmptyPayload | { "type": "render_http_request_request" } & RenderHttpRequestRequest | { "type": "render_http_request_response" } & RenderHttpRequestResponse | { "type": "get_key_value_request" } & GetKeyValueRequest | { "type": "get_key_value_response" } & GetKeyValueResponse | { "type": "set_key_value_request" } & SetKeyValueRequest | { "type": "set_key_value_response" } & SetKeyValueResponse | { "type": "delete_key_value_request" } & DeleteKeyValueRequest | { "type": "delete_key_value_response" } & DeleteKeyValueResponse | { "type": "open_window_request" } & OpenWindowRequest | { "type": "window_navigate_event" } & WindowNavigateEvent | { "type": "window_close_event" } | { "type": "close_window_request" } & CloseWindowRequest | { "type": "template_render_request" } & TemplateRenderRequest | { "type": "template_render_response" } & TemplateRenderResponse | { "type": "show_toast_request" } & ShowToastRequest | { "type": "show_toast_response" } & EmptyPayload | { "type": "prompt_text_request" } & PromptTextRequest | { "type": "prompt_text_response" } & PromptTextResponse | { "type": "get_http_request_by_id_request" } & GetHttpRequestByIdRequest | { "type": "get_http_request_by_id_response" } & GetHttpRequestByIdResponse | { "type": "find_http_responses_request" } & FindHttpResponsesRequest | { "type": "find_http_responses_response" } & FindHttpResponsesResponse | { "type": "empty_response" } & EmptyPayload | { "type": "error_response" } & ErrorResponse;
export type JsonPrimitive = string | number | boolean | null;
export type OpenWindowRequest = { url: string,
/**
* Label for the window. If not provided, a random one will be generated.
*/
label: string, title?: string, size?: WindowSize, dataDirKey?: string, };
export type PluginWindowContext = { "type": "none" } | { "type": "label", label: string, workspace_id: string | null, };
export type PromptTextRequest = { id: string, title: string, label: string, description?: string, defaultValue?: string, placeholder?: string,
/**
* Text to add to the confirmation button
*/
confirmText?: string,
/**
* Text to add to the cancel button
*/
cancelText?: string,
/**
* Require the user to enter a non-empty value
*/
required?: boolean, };
export type PromptTextResponse = { value: string | null, };
export type RenderHttpRequestRequest = { httpRequest: HttpRequest, purpose: RenderPurpose, };
export type RenderHttpRequestResponse = { httpRequest: HttpRequest, };
export type RenderPurpose = "send" | "preview";
export type SendHttpRequestRequest = { httpRequest: Partial<HttpRequest>, };
export type SendHttpRequestResponse = { httpResponse: HttpResponse, };
export type SetKeyValueRequest = { key: string, value: string, };
export type SetKeyValueResponse = {};
export type ShowToastRequest = { message: string, color?: Color, icon?: Icon, };
export type TemplateFunction = { name: string, description?: string,
/**
* Also support alternative names. This is useful for not breaking existing
* tags when changing the `name` property
*/
aliases?: Array<string>, args: Array<TemplateFunctionArg>, };
/**
* Similar to FormInput, but contains
*/
export type TemplateFunctionArg = FormInput;
export type TemplateRenderRequest = { data: JsonValue, purpose: RenderPurpose, };
export type TemplateRenderResponse = { data: JsonValue, };
export type WindowNavigateEvent = { url: string, };
export type WindowSize = { width: number, height: number, };

View File

@@ -1,27 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type Environment = { model: "environment", id: string, workspaceId: string, createdAt: string, updatedAt: string, name: string, public: boolean, base: boolean, variables: Array<EnvironmentVariable>, };
export type EnvironmentVariable = { enabled?: boolean, name: string, value: string, id?: string, };
export type Folder = { model: "folder", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, name: string, description: string, sortPriority: number, };
export type GrpcMetadataEntry = { enabled?: boolean, name: string, value: string, id?: string, };
export type GrpcRequest = { model: "grpc_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authenticationType: string | null, authentication: Record<string, any>, description: string, message: string, metadata: Array<GrpcMetadataEntry>, method: string | null, name: string, service: string | null, sortPriority: number, url: string, };
export type HttpRequest = { model: "http_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, body: Record<string, any>, bodyType: string | null, description: string, headers: Array<HttpRequestHeader>, method: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
export type HttpRequestHeader = { enabled?: boolean, name: string, value: string, id?: string, };
export type HttpResponse = { model: "http_response", id: string, createdAt: string, updatedAt: string, workspaceId: string, requestId: string, bodyPath: string | null, contentLength: number | null, elapsed: number, elapsedHeaders: number, error: string | null, headers: Array<HttpResponseHeader>, remoteAddr: string | null, status: number, statusReason: string | null, state: HttpResponseState, url: string, version: string | null, };
export type HttpResponseHeader = { name: string, value: string, };
export type HttpResponseState = "initialized" | "connected" | "closed";
export type HttpUrlParameter = { enabled?: boolean, name: string, value: string, id?: string, };
export type WebsocketRequest = { model: "websocket_request", id: string, createdAt: string, updatedAt: string, workspaceId: string, folderId: string | null, authentication: Record<string, any>, authenticationType: string | null, description: string, headers: Array<HttpRequestHeader>, message: string, name: string, sortPriority: number, url: string, urlParameters: Array<HttpUrlParameter>, };
export type Workspace = { model: "workspace", id: string, createdAt: string, updatedAt: string, name: string, description: string, encryptionKeyChallenge: string | null, settingValidateCertificates: boolean, settingFollowRedirects: boolean, settingRequestTimeout: number, };

View File

@@ -1,3 +0,0 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
export type JsonValue = number | string | boolean | Array<JsonValue> | { [key in string]?: JsonValue } | null;

View File

@@ -1,2 +0,0 @@
export type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
export type MaybePromise<T> = Promise<T> | T;

View File

@@ -1,9 +0,0 @@
export type * from './plugins';
export type * from './themes';
export * from './bindings/gen_models';
export * from './bindings/gen_events';
// Some extras for utility
export type { PartialImportResources } from './plugins/ImporterPlugin';

View File

@@ -1,29 +0,0 @@
import {
CallHttpAuthenticationActionArgs,
CallHttpAuthenticationRequest,
CallHttpAuthenticationResponse,
FormInput,
GetHttpAuthenticationConfigRequest,
GetHttpAuthenticationSummaryResponse,
HttpAuthenticationAction,
} from '../bindings/gen_events';
import { MaybePromise } from '../helpers';
import { Context } from './Context';
type DynamicFormInput = FormInput & {
dynamic(
ctx: Context,
args: GetHttpAuthenticationConfigRequest,
): MaybePromise<Partial<FormInput> | undefined | null>;
};
export type AuthenticationPlugin = GetHttpAuthenticationSummaryResponse & {
args: (FormInput | DynamicFormInput)[];
onApply(
ctx: Context,
args: CallHttpAuthenticationRequest,
): MaybePromise<CallHttpAuthenticationResponse>;
actions?: (HttpAuthenticationAction & {
onSelect(ctx: Context, args: CallHttpAuthenticationActionArgs): Promise<void> | void;
})[];
};

View File

@@ -1,52 +0,0 @@
import type {
FindHttpResponsesRequest,
FindHttpResponsesResponse,
GetHttpRequestByIdRequest,
GetHttpRequestByIdResponse,
OpenWindowRequest,
PromptTextRequest,
PromptTextResponse,
RenderHttpRequestRequest,
RenderHttpRequestResponse,
SendHttpRequestRequest,
SendHttpRequestResponse,
ShowToastRequest,
TemplateRenderRequest,
TemplateRenderResponse,
} from '../bindings/gen_events.ts';
export interface Context {
clipboard: {
copyText(text: string): Promise<void>;
};
toast: {
show(args: ShowToastRequest): Promise<void>;
};
prompt: {
text(args: PromptTextRequest): Promise<PromptTextResponse['value']>;
};
store: {
set<T>(key: string, value: T): Promise<void>;
get<T>(key: string): Promise<T | undefined>;
delete(key: string): Promise<boolean>;
};
window: {
openUrl(
args: OpenWindowRequest & {
onNavigate?: (args: { url: string }) => void;
onClose?: () => void;
},
): Promise<{ close: () => void }>;
};
httpRequest: {
send(args: SendHttpRequestRequest): Promise<SendHttpRequestResponse['httpResponse']>;
getById(args: GetHttpRequestByIdRequest): Promise<GetHttpRequestByIdResponse['httpRequest']>;
render(args: RenderHttpRequestRequest): Promise<RenderHttpRequestResponse['httpRequest']>;
};
httpResponse: {
find(args: FindHttpResponsesRequest): Promise<FindHttpResponsesResponse['httpResponses']>;
};
templates: {
render(args: TemplateRenderRequest): Promise<TemplateRenderResponse['data']>;
};
}

View File

@@ -1,12 +0,0 @@
import type { Context } from './Context';
type FilterPluginResponse = { filtered: string };
export type FilterPlugin = {
name: string;
description?: string;
onFilter(
ctx: Context,
args: { payload: string; filter: string; mimeType: string },
): Promise<FilterPluginResponse> | FilterPluginResponse;
};

View File

@@ -1,6 +0,0 @@
import type { CallHttpRequestActionArgs, HttpRequestAction } from '../bindings/gen_events';
import type { Context } from './Context';
export type HttpRequestActionPlugin = HttpRequestAction & {
onSelect(ctx: Context, args: CallHttpRequestActionArgs): Promise<void> | void;
};

View File

@@ -1,25 +0,0 @@
import { ImportResources } from '../bindings/gen_events';
import { AtLeast } from '../helpers';
import type { Context } from './Context';
type RootFields = 'name' | 'id' | 'model';
type CommonFields = RootFields | 'workspaceId';
export type PartialImportResources = {
workspaces: Array<AtLeast<ImportResources['workspaces'][0], RootFields>>;
environments: Array<AtLeast<ImportResources['environments'][0], CommonFields>>;
folders: Array<AtLeast<ImportResources['folders'][0], CommonFields>>;
httpRequests: Array<AtLeast<ImportResources['httpRequests'][0], CommonFields>>;
grpcRequests: Array<AtLeast<ImportResources['grpcRequests'][0], CommonFields>>;
websocketRequests: Array<AtLeast<ImportResources['websocketRequests'][0], CommonFields>>;
};
export type ImportPluginResponse = null | {
resources: PartialImportResources;
};
export type ImporterPlugin = {
name: string;
description?: string;
onImport(ctx: Context, args: { text: string }): Promise<ImportPluginResponse>;
};

View File

@@ -1,12 +0,0 @@
import {
CallTemplateFunctionArgs,
TemplateFunction,
} from "../bindings/gen_events";
import { Context } from "./Context";
export type TemplateFunctionPlugin = TemplateFunction & {
onRender(
ctx: Context,
args: CallTemplateFunctionArgs,
): Promise<string | null>;
};

View File

@@ -1,8 +0,0 @@
import { Index } from "../themes";
import { Context } from "./Context";
export type ThemePlugin = {
name: string;
description?: string;
getTheme(ctx: Context, fileContents: string): Promise<Index>;
};

View File

@@ -1,20 +0,0 @@
import { AuthenticationPlugin } from './AuthenticationPlugin';
import type { FilterPlugin } from './FilterPlugin';
import type { HttpRequestActionPlugin } from './HttpRequestActionPlugin';
import type { ImporterPlugin } from './ImporterPlugin';
import type { TemplateFunctionPlugin } from './TemplateFunctionPlugin';
import type { ThemePlugin } from './ThemePlugin';
export type { Context } from './Context';
/**
* The global structure of a Yaak plugin
*/
export type PluginDefinition = {
importer?: ImporterPlugin;
theme?: ThemePlugin;
filter?: FilterPlugin;
authentication?: AuthenticationPlugin;
httpRequestActions?: HttpRequestActionPlugin[];
templateFunctions?: TemplateFunctionPlugin[];
};

View File

@@ -1,44 +0,0 @@
export type Colors = {
surface: string;
surfaceHighlight?: string;
surfaceActive?: string;
text: string;
textSubtle?: string;
textSubtlest?: string;
border?: string;
borderSubtle?: string;
borderFocus?: string;
shadow?: string;
backdrop?: string;
selection?: string;
primary?: string;
secondary?: string;
info?: string;
success?: string;
notice?: string;
warning?: string;
danger?: string;
};
export type Index = Colors & {
id: string;
name: string;
components?: Partial<{
dialog: Partial<Colors>;
menu: Partial<Colors>;
toast: Partial<Colors>;
sidebar: Partial<Colors>;
responsePane: Partial<Colors>;
appHeader: Partial<Colors>;
button: Partial<Colors>;
banner: Partial<Colors>;
placeholder: Partial<Colors>;
urlBar: Partial<Colors>;
editor: Partial<Colors>;
input: Partial<Colors>;
}>;
};

View File

@@ -1,15 +0,0 @@
{
"compilerOptions": {
"module": "node16",
"target": "es6",
"lib": ["es2021"],
"declaration": true,
"declarationDir": "./lib",
"outDir": "./lib",
"strict": true,
"types": ["node"]
},
"files": [
"src/index.ts"
]
}

View File

@@ -1,10 +0,0 @@
{
"name": "@yaakapp-internal/plugin-runtime",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@yaakapp-internal/plugin-runtime"
}
}
}

View File

@@ -1,14 +0,0 @@
{
"name": "@yaakapp-internal/plugin-runtime",
"scripts": {
"bootstrap": "npm run build",
"build": "run-p build:*",
"build:main": "esbuild src/index.ts --bundle --platform=node --outfile=../../src-tauri/vendored/plugin-runtime/index.cjs"
},
"dependencies": {
"ws": "^8.18.0"
},
"devDependencies": {
"@types/ws": "^8.5.13"
}
}

View File

@@ -1,19 +0,0 @@
import type { InternalEvent } from '@yaakapp/api';
export class EventChannel {
#listeners = new Set<(event: InternalEvent) => void>();
emit(e: InternalEvent) {
for (const l of this.#listeners) {
l(e);
}
}
listen(cb: (e: InternalEvent) => void) {
this.#listeners.add(cb);
}
unlisten(cb: (e: InternalEvent) => void) {
this.#listeners.delete(cb);
}
}

View File

@@ -1,27 +0,0 @@
import type { BootRequest, InternalEvent } from '@yaakapp/api';
import type { EventChannel } from './EventChannel';
import { PluginInstance, PluginWorkerData } from './PluginInstance';
export class PluginHandle {
#instance: PluginInstance;
constructor(
readonly pluginRefId: string,
readonly bootRequest: BootRequest,
readonly pluginToAppEvents: EventChannel,
) {
const workerData: PluginWorkerData = {
pluginRefId: this.pluginRefId,
bootRequest: this.bootRequest,
};
this.#instance = new PluginInstance(workerData, pluginToAppEvents);
}
sendToWorker(event: InternalEvent) {
this.#instance.postMessage(event);
}
terminate() {
this.#instance.terminate();
}
}

View File

@@ -1,582 +0,0 @@
import { PluginWindowContext, TemplateFunctionArg } from '@yaakapp-internal/plugins';
import type {
BootRequest,
Context,
DeleteKeyValueResponse,
FindHttpResponsesResponse,
FormInput,
GetHttpRequestByIdResponse,
GetKeyValueResponse,
HttpAuthenticationAction,
HttpRequestAction,
InternalEvent,
InternalEventPayload,
JsonPrimitive,
PluginDefinition,
PromptTextResponse,
RenderHttpRequestResponse,
SendHttpRequestResponse,
TemplateFunction,
TemplateRenderResponse,
} from '@yaakapp/api';
import console from 'node:console';
import { readFileSync, type Stats, statSync, watch } from 'node:fs';
import path from 'node:path';
// import util from 'node:util';
import { EventChannel } from './EventChannel';
// import { interceptStdout } from './interceptStdout';
import { migrateTemplateFunctionSelectOptions } from './migrations';
export interface PluginWorkerData {
bootRequest: BootRequest;
pluginRefId: string;
}
export class PluginInstance {
#workerData: PluginWorkerData;
#mod: PluginDefinition;
#pkg: { name?: string; version?: string };
#pluginToAppEvents: EventChannel;
#appToPluginEvents: EventChannel;
constructor(workerData: PluginWorkerData, pluginEvents: EventChannel) {
this.#workerData = workerData;
this.#pluginToAppEvents = pluginEvents;
this.#appToPluginEvents = new EventChannel();
// Forward incoming events to onMessage()
this.#appToPluginEvents.listen(async (event) => {
await this.#onMessage(event);
});
// Reload plugin if the JS or package.json changes
const windowContextNone: PluginWindowContext = { type: 'none' };
const fileChangeCallback = async () => {
this.#importModule();
return this.#sendPayload(windowContextNone, { type: 'reload_response' }, null);
};
if (this.#workerData.bootRequest.watch) {
watchFile(this.#pathMod(), fileChangeCallback);
watchFile(this.#pathPkg(), fileChangeCallback);
}
this.#mod = {};
this.#pkg = JSON.parse(readFileSync(this.#pathPkg(), 'utf8'));
// TODO: Re-implement this now that we're not using workers
// prefixStdout(`[plugin][${this.#pkg.name}] %s`);
this.#importModule();
}
postMessage(event: InternalEvent) {
this.#appToPluginEvents.emit(event);
}
terminate() {
this.#unimportModule();
}
async #onMessage(event: InternalEvent) {
const ctx = this.#newCtx(event);
const { windowContext, payload, id: replyId } = event;
try {
if (payload.type === 'boot_request') {
// console.log('Plugin initialized', pkg.name, { capabilities, enableWatch });
const payload: InternalEventPayload = {
type: 'boot_response',
name: this.#pkg.name ?? 'unknown',
version: this.#pkg.version ?? '0.0.1',
};
this.#sendPayload(windowContext, payload, replyId);
return;
}
if (payload.type === 'terminate_request') {
const payload: InternalEventPayload = {
type: 'terminate_response',
};
this.#sendPayload(windowContext, payload, replyId);
return;
}
if (
payload.type === 'import_request' &&
typeof this.#mod?.importer?.onImport === 'function'
) {
const reply = await this.#mod.importer.onImport(ctx, {
text: payload.content,
});
if (reply != null) {
const replyPayload: InternalEventPayload = {
type: 'import_response',
// deno-lint-ignore no-explicit-any
resources: reply.resources as any,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
} else {
// Continue, to send back an empty reply
}
}
if (payload.type === 'filter_request' && typeof this.#mod?.filter?.onFilter === 'function') {
const reply = await this.#mod.filter.onFilter(ctx, {
filter: payload.filter,
payload: payload.content,
mimeType: payload.type,
});
const replyPayload: InternalEventPayload = {
type: 'filter_response',
content: reply.filtered,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
}
if (
payload.type === 'get_http_request_actions_request' &&
Array.isArray(this.#mod?.httpRequestActions)
) {
const reply: HttpRequestAction[] = this.#mod.httpRequestActions.map((a) => ({
...a,
// Add everything except onSelect
onSelect: undefined,
}));
const replyPayload: InternalEventPayload = {
type: 'get_http_request_actions_response',
pluginRefId: this.#workerData.pluginRefId,
actions: reply,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
}
if (
payload.type === 'get_template_functions_request' &&
Array.isArray(this.#mod?.templateFunctions)
) {
const reply: TemplateFunction[] = this.#mod.templateFunctions.map((templateFunction) => {
return {
...migrateTemplateFunctionSelectOptions(templateFunction),
// Add everything except render
onRender: undefined,
};
});
const replyPayload: InternalEventPayload = {
type: 'get_template_functions_response',
pluginRefId: this.#workerData.pluginRefId,
functions: reply,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
}
if (payload.type === 'get_http_authentication_summary_request' && this.#mod?.authentication) {
const { name, shortLabel, label } = this.#mod.authentication;
const replyPayload: InternalEventPayload = {
type: 'get_http_authentication_summary_response',
name,
label,
shortLabel,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
}
if (payload.type === 'get_http_authentication_config_request' && this.#mod?.authentication) {
const { args, actions } = this.#mod.authentication;
const resolvedArgs: FormInput[] = [];
for (let i = 0; i < args.length; i++) {
let v = args[i];
if ('dynamic' in v) {
const dynamicAttrs = await v.dynamic(ctx, payload);
const { dynamic, ...other } = v;
resolvedArgs.push({ ...other, ...dynamicAttrs } as FormInput);
} else {
resolvedArgs.push(v);
}
}
const resolvedActions: HttpAuthenticationAction[] = [];
for (const { onSelect, ...action } of actions ?? []) {
resolvedActions.push(action);
}
const replyPayload: InternalEventPayload = {
type: 'get_http_authentication_config_response',
args: resolvedArgs,
actions: resolvedActions,
pluginRefId: this.#workerData.pluginRefId,
};
this.#sendPayload(windowContext, replyPayload, replyId);
return;
}
if (payload.type === 'call_http_authentication_request' && this.#mod?.authentication) {
const auth = this.#mod.authentication;
if (typeof auth?.onApply === 'function') {
applyFormInputDefaults(auth.args, payload.values);
const result = await auth.onApply(ctx, payload);
this.#sendPayload(
windowContext,
{
type: 'call_http_authentication_response',
setHeaders: result.setHeaders,
},
replyId,
);
return;
}
}
if (
payload.type === 'call_http_authentication_action_request' &&
this.#mod.authentication != null
) {
const action = this.#mod.authentication.actions?.[payload.index];
if (typeof action?.onSelect === 'function') {
await action.onSelect(ctx, payload.args);
this.#sendEmpty(windowContext, replyId);
return;
}
}
if (
payload.type === 'call_http_request_action_request' &&
Array.isArray(this.#mod.httpRequestActions)
) {
const action = this.#mod.httpRequestActions[payload.index];
if (typeof action?.onSelect === 'function') {
await action.onSelect(ctx, payload.args);
this.#sendEmpty(windowContext, replyId);
return;
}
}
if (
payload.type === 'call_template_function_request' &&
Array.isArray(this.#mod?.templateFunctions)
) {
const fn = this.#mod.templateFunctions.find((a) => a.name === payload.name);
if (typeof fn?.onRender === 'function') {
applyFormInputDefaults(fn.args, payload.args.values);
const result = await fn.onRender(ctx, payload.args);
this.#sendPayload(
windowContext,
{
type: 'call_template_function_response',
value: result ?? null,
},
replyId,
);
return;
}
}
if (payload.type === 'reload_request') {
this.#importModule();
}
} catch (err) {
console.log('Plugin call threw exception', payload.type, err);
this.#sendPayload(
windowContext,
{
type: 'error_response',
error: `${err}`,
},
replyId,
);
return;
}
// No matches, so send back an empty response so the caller doesn't block forever
this.#sendEmpty(windowContext, replyId);
}
#pathMod() {
return path.posix.join(this.#workerData.bootRequest.dir, 'build', 'index.js');
}
#pathPkg() {
return path.join(this.#workerData.bootRequest.dir, 'package.json');
}
#unimportModule() {
const id = require.resolve(this.#pathMod());
delete require.cache[id];
}
#importModule() {
const id = require.resolve(this.#pathMod());
delete require.cache[id];
this.#mod = require(id).plugin;
}
#buildEventToSend(
windowContext: PluginWindowContext,
payload: InternalEventPayload,
replyId: string | null = null,
): InternalEvent {
return {
pluginRefId: this.#workerData.pluginRefId,
pluginName: path.basename(this.#workerData.bootRequest.dir),
id: genId(),
replyId,
payload,
windowContext,
};
}
#sendPayload(
windowContext: PluginWindowContext,
payload: InternalEventPayload,
replyId: string | null,
): string {
const event = this.#buildEventToSend(windowContext, payload, replyId);
this.#sendEvent(event);
return event.id;
}
#sendEvent(event: InternalEvent) {
// if (event.payload.type !== 'empty_response') {
// console.log('Sending event to app', this.#pkg.name, event.id, event.payload.type);
// }
this.#pluginToAppEvents.emit(event);
}
#sendEmpty(windowContext: PluginWindowContext, replyId: string | null = null): string {
return this.#sendPayload(windowContext, { type: 'empty_response' }, replyId);
}
#sendAndWaitForReply<T extends Omit<InternalEventPayload, 'type'>>(
windowContext: PluginWindowContext,
payload: InternalEventPayload,
): Promise<T> {
// 1. Build event to send
const eventToSend = this.#buildEventToSend(windowContext, payload, null);
// 2. Spawn listener in background
const promise = new Promise<T>((resolve) => {
const cb = (event: InternalEvent) => {
if (event.replyId === eventToSend.id) {
this.#appToPluginEvents.unlisten(cb); // Unlisten, now that we're done
const { type: _, ...payload } = event.payload;
resolve(payload as T);
}
};
this.#appToPluginEvents.listen(cb);
});
// 3. Send the event after we start listening (to prevent race)
this.#sendEvent(eventToSend);
// 4. Return the listener promise
return promise as unknown as Promise<T>;
}
#sendAndListenForEvents(
windowContext: PluginWindowContext,
payload: InternalEventPayload,
onEvent: (event: InternalEventPayload) => void,
): void {
// 1. Build event to send
const eventToSend = this.#buildEventToSend(windowContext, payload, null);
// 2. Listen for replies in the background
this.#appToPluginEvents.listen((event: InternalEvent) => {
if (event.replyId === eventToSend.id) {
onEvent(event.payload);
}
});
// 3. Send the event after we start listening (to prevent race)
this.#sendEvent(eventToSend);
}
#newCtx(event: InternalEvent): Context {
return {
clipboard: {
copyText: async (text) => {
await this.#sendAndWaitForReply(event.windowContext, {
type: 'copy_text_request',
text,
});
},
},
toast: {
show: async (args) => {
await this.#sendAndWaitForReply(event.windowContext, {
type: 'show_toast_request',
...args,
});
},
},
window: {
openUrl: async ({ onNavigate, onClose, ...args }) => {
args.label = args.label || `${Math.random()}`;
const payload: InternalEventPayload = { type: 'open_window_request', ...args };
const onEvent = (event: InternalEventPayload) => {
if (event.type === 'window_navigate_event') {
onNavigate?.(event);
} else if (event.type === 'window_close_event') {
onClose?.();
}
};
this.#sendAndListenForEvents(event.windowContext, payload, onEvent);
return {
close: () => {
const closePayload: InternalEventPayload = {
type: 'close_window_request',
label: args.label,
};
this.#sendPayload(event.windowContext, closePayload, null);
},
};
},
},
prompt: {
text: async (args) => {
const reply: PromptTextResponse = await this.#sendAndWaitForReply(event.windowContext, {
type: 'prompt_text_request',
...args,
});
return reply.value;
},
},
httpResponse: {
find: async (args) => {
const payload = {
type: 'find_http_responses_request',
...args,
} as const;
const { httpResponses } = await this.#sendAndWaitForReply<FindHttpResponsesResponse>(
event.windowContext,
payload,
);
return httpResponses;
},
},
httpRequest: {
getById: async (args) => {
const payload = {
type: 'get_http_request_by_id_request',
...args,
} as const;
const { httpRequest } = await this.#sendAndWaitForReply<GetHttpRequestByIdResponse>(
event.windowContext,
payload,
);
return httpRequest;
},
send: async (args) => {
const payload = {
type: 'send_http_request_request',
...args,
} as const;
const { httpResponse } = await this.#sendAndWaitForReply<SendHttpRequestResponse>(
event.windowContext,
payload,
);
return httpResponse;
},
render: async (args) => {
const payload = {
type: 'render_http_request_request',
...args,
} as const;
const { httpRequest } = await this.#sendAndWaitForReply<RenderHttpRequestResponse>(
event.windowContext,
payload,
);
return httpRequest;
},
},
templates: {
/**
* Invoke Yaak's template engine to render a value. If the value is a nested type
* (eg. object), it will be recursively rendered.
*/
render: async (args) => {
const payload = { type: 'template_render_request', ...args } as const;
const result = await this.#sendAndWaitForReply<TemplateRenderResponse>(
event.windowContext,
payload,
);
return result.data;
},
},
store: {
get: async <T>(key: string) => {
const payload = { type: 'get_key_value_request', key } as const;
const result = await this.#sendAndWaitForReply<GetKeyValueResponse>(
event.windowContext,
payload,
);
return result.value ? (JSON.parse(result.value) as T) : undefined;
},
set: async <T>(key: string, value: T) => {
const valueStr = JSON.stringify(value);
const payload: InternalEventPayload = {
type: 'set_key_value_request',
key,
value: valueStr,
};
await this.#sendAndWaitForReply<GetKeyValueResponse>(event.windowContext, payload);
},
delete: async (key: string) => {
const payload = { type: 'delete_key_value_request', key } as const;
const result = await this.#sendAndWaitForReply<DeleteKeyValueResponse>(
event.windowContext,
payload,
);
return result.deleted;
},
},
};
}
}
function genId(len = 5): string {
const alphabet = '01234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let id = '';
for (let i = 0; i < len; i++) {
id += alphabet[Math.floor(Math.random() * alphabet.length)];
}
return id;
}
/** Recursively apply form input defaults to a set of values */
function applyFormInputDefaults(
inputs: TemplateFunctionArg[],
values: { [p: string]: JsonPrimitive | undefined },
) {
for (const input of inputs) {
if ('inputs' in input) {
applyFormInputDefaults(input.inputs ?? [], values);
} else if ('defaultValue' in input && values[input.name] === undefined) {
values[input.name] = input.defaultValue;
}
}
}
const watchedFiles: Record<string, Stats> = {};
/**
* Watch a file and trigger callback on change.
*
* We also track the stat for each file because fs.watch() will
* trigger a "change" event when the access date changes
*/
function watchFile(filepath: string, cb: (filepath: string) => void) {
watch(filepath, () => {
const stat = statSync(filepath);
if (stat.mtimeMs !== watchedFiles[filepath]?.mtimeMs) {
cb(filepath);
}
watchedFiles[filepath] = stat;
});
}

View File

@@ -1,55 +0,0 @@
import type { InternalEvent } from '@yaakapp/api';
import { EventChannel } from './EventChannel';
import { PluginHandle } from './PluginHandle';
import WebSocket from 'ws';
const port = process.env.PORT;
if (!port) {
throw new Error('Plugin runtime missing PORT')
}
const pluginToAppEvents = new EventChannel();
const plugins: Record<string, PluginHandle> = {};
const ws = new WebSocket(`ws://localhost:${port}`);
ws.on('message', async (e: Buffer) => {
try {
await handleIncoming(e.toString());
} catch (err) {
console.log('Failed to handle incoming plugin event', err);
}
});
ws.on('open', () => console.log('Plugin runtime connected to websocket'));
ws.on('error', (err: any) => console.error('Plugin runtime websocket error', err));
ws.on('close', (code: number) => console.log('Plugin runtime websocket closed', code));
// Listen for incoming events from plugins
pluginToAppEvents.listen((e) => {
const eventStr = JSON.stringify(e);
ws.send(eventStr);
});
async function handleIncoming(msg: string) {
const pluginEvent: InternalEvent = JSON.parse(msg);
// Handle special event to bootstrap plugin
if (pluginEvent.payload.type === 'boot_request') {
const plugin = new PluginHandle(pluginEvent.pluginRefId, pluginEvent.payload, pluginToAppEvents);
plugins[pluginEvent.pluginRefId] = plugin;
}
// Once booted, forward all events to the plugin worker
const plugin = plugins[pluginEvent.pluginRefId];
if (!plugin) {
console.warn('Failed to get plugin for event by', pluginEvent.pluginRefId);
return;
}
if (pluginEvent.payload.type === 'terminate_request') {
plugin.terminate();
console.log('Terminated plugin worker', pluginEvent.pluginRefId);
delete plugins[pluginEvent.pluginRefId];
}
plugin.sendToWorker(pluginEvent);
}

View File

@@ -1,37 +0,0 @@
import process from "node:process";
export function interceptStdout(
intercept: (text: string) => string,
) {
const old_stdout_write = process.stdout.write;
const old_stderr_write = process.stderr.write;
process.stdout.write = (function (write) {
return function (text: string) {
arguments[0] = interceptor(text, intercept);
// deno-lint-ignore no-explicit-any
write.apply(process.stdout, arguments as any);
return true;
};
})(process.stdout.write);
process.stderr.write = (function (write) {
return function (text: string) {
arguments[0] = interceptor(text, intercept);
// deno-lint-ignore no-explicit-any
write.apply(process.stderr, arguments as any);
return true;
};
})(process.stderr.write);
// puts back to original
return function unhook() {
process.stdout.write = old_stdout_write;
process.stderr.write = old_stderr_write;
};
}
function interceptor(text: string, fn: (text: string) => string) {
return fn(text).replace(/\n$/, "") +
(fn(text) && /\n$/.test(text) ? "\n" : "");
}

View File

@@ -1,18 +0,0 @@
import { TemplateFunction } from '@yaakapp/api';
export function migrateTemplateFunctionSelectOptions(f: TemplateFunction): TemplateFunction {
const migratedArgs = f.args.map((a) => {
if (a.type === 'select') {
a.options = a.options.map((o) => ({
...o,
label: o.label || (o as any).name,
}));
}
return a;
});
return {
...f,
args: migratedArgs,
};
}

View File

@@ -1,25 +0,0 @@
{
"compilerOptions": {
"module": "node16",
"strict": true,
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"target": "es2021",
"lib": ["es2021"],
"noImplicitAny": false,
"moduleResolution": "node16",
"resolveJsonModule": true,
"sourceMap": true,
"outDir": "build",
"baseUrl": ".",
"paths": {
"*": [
"node_modules/*",
"src/types/*"
]
}
},
"include": [
"src"
]
}

173
plugins/filter-jsonpath/package-lock.json generated Normal file
View File

@@ -0,0 +1,173 @@
{
"name": "filter-jsonpath",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "filter-jsonpath",
"version": "0.0.1",
"dependencies": {
"jsonpath": "^1.1.1"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="
},
"node_modules/escodegen": {
"version": "1.14.3",
"resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
"integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
"dependencies": {
"esprima": "^4.0.1",
"estraverse": "^4.2.0",
"esutils": "^2.0.2",
"optionator": "^0.8.1"
},
"bin": {
"escodegen": "bin/escodegen.js",
"esgenerate": "bin/esgenerate.js"
},
"engines": {
"node": ">=4.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
"node_modules/escodegen/node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/esprima": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-1.2.2.tgz",
"integrity": "sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"engines": {
"node": ">=4.0"
}
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
},
"node_modules/jsonpath": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/jsonpath/-/jsonpath-1.1.1.tgz",
"integrity": "sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==",
"dependencies": {
"esprima": "1.2.2",
"static-eval": "2.0.2",
"underscore": "1.12.1"
}
},
"node_modules/levn": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
"integrity": "sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
"dependencies": {
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/optionator": {
"version": "0.8.3",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
"integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
"dependencies": {
"deep-is": "~0.1.3",
"fast-levenshtein": "~2.0.6",
"levn": "~0.3.0",
"prelude-ls": "~1.1.2",
"type-check": "~0.3.2",
"word-wrap": "~1.2.3"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/prelude-ls": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
"integrity": "sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"optional": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/static-eval": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz",
"integrity": "sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==",
"dependencies": {
"escodegen": "^1.8.1"
}
},
"node_modules/type-check": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
"integrity": "sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
"dependencies": {
"prelude-ls": "~1.1.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/underscore": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.12.1.tgz",
"integrity": "sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw=="
},
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"engines": {
"node": ">=0.10.0"
}
}
}
}

View File

@@ -0,0 +1,7 @@
{
"name": "filter-jsonpath",
"version": "0.0.1",
"dependencies": {
"jsonpath": "^1.1.1"
}
}

View File

@@ -0,0 +1,12 @@
import jp from 'jsonpath';
export function pluginHookResponseFilter(filter, text) {
let parsed;
try {
parsed = JSON.parse(text);
} catch (e) {
return;
}
const filtered = jp.query(parsed, filter);
return { filtered: JSON.stringify(filtered, null, 2) };
}

View File

@@ -0,0 +1,13 @@
import { resolve } from 'path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.js'),
fileName: 'index',
formats: ['es'],
},
outDir: resolve(__dirname, '../../src-tauri/plugins/filter-jsonpath'),
},
});

32
plugins/filter-xpath/package-lock.json generated Normal file
View File

@@ -0,0 +1,32 @@
{
"name": "filter-xpath",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "filter-xpath",
"version": "0.0.1",
"dependencies": {
"@xmldom/xmldom": "^0.8.10",
"xpath": "^0.0.34"
}
},
"node_modules/@xmldom/xmldom": {
"version": "0.8.10",
"resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
"integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/xpath": {
"version": "0.0.34",
"resolved": "https://registry.npmjs.org/xpath/-/xpath-0.0.34.tgz",
"integrity": "sha512-FxF6+rkr1rNSQrhUNYrAFJpRXNzlDoMxeXN5qI84939ylEv3qqPFKa85Oxr6tDaJKqwW6KKyo2v26TSv3k6LeA==",
"engines": {
"node": ">=0.6.0"
}
}
}
}

View File

@@ -0,0 +1,8 @@
{
"name": "filter-xpath",
"version": "0.0.1",
"dependencies": {
"@xmldom/xmldom": "^0.8.10",
"xpath": "^0.0.34"
}
}

View File

@@ -0,0 +1,8 @@
import xpath from 'xpath';
import { DOMParser } from '@xmldom/xmldom';
export function pluginHookResponseFilter(filter, text) {
const doc = new DOMParser().parseFromString(text, 'text/xml');
const filtered = `${xpath.select(filter, doc)}`;
return { filtered };
}

View File

@@ -0,0 +1,13 @@
import { resolve } from 'path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.js'),
fileName: 'index',
formats: ['es'],
},
outDir: resolve(__dirname, '../../src-tauri/plugins/filter-xpath'),
},
});

View File

@@ -0,0 +1,12 @@
{
"name": "importer-insomnia",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "importer-insomnia",
"version": "0.0.1"
}
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "importer-insomnia",
"version": "0.0.1"
}

View File

@@ -0,0 +1,23 @@
export function isWorkspace(obj) {
return isJSObject(obj) && obj._type === 'workspace';
}
export function isRequestGroup(obj) {
return isJSObject(obj) && obj._type === 'request_group';
}
export function isRequest(obj) {
return isJSObject(obj) && obj._type === 'request';
}
export function isEnvironment(obj) {
return isJSObject(obj) && obj._type === 'environment';
}
export function isJSObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}
export function isJSString(obj) {
return Object.prototype.toString.call(obj) === '[object String]';
}

View File

@@ -0,0 +1,18 @@
import { isJSString } from './types.js';
export function parseVariables(data) {
return Object.entries(data).map(([name, value]) => ({
enabled: true,
name,
value: `${value}`,
}));
}
/**
* Convert Insomnia syntax to Yaak syntax
* @param {string} variable - Text to convert
*/
export function convertSyntax(variable) {
if (!isJSString(variable)) return variable;
return variable.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, '${[$2]}');
}

View File

@@ -0,0 +1,21 @@
/**
* Import an Insomnia environment object.
* @param {Object} e - The environment object to import.
* @param workspaceId - Workspace to import into.
*/
export function importEnvironment(e, workspaceId) {
console.log('IMPORTING Environment', e._id, e.name, JSON.stringify(e, null, 2));
return {
id: e._id,
createdAt: new Date(e.created ?? Date.now()).toISOString().replace('Z', ''),
updatedAt: new Date(e.updated ?? Date.now()).toISOString().replace('Z', ''),
workspaceId,
model: 'environment',
name: e.name,
variables: Object.entries(e.data).map(([name, value]) => ({
enabled: true,
name,
value: `${value}`,
})),
};
}

View File

@@ -0,0 +1,17 @@
/**
* Import an Insomnia folder object.
* @param {Object} f - The environment object to import.
* @param workspaceId - Workspace to import into.
*/
export function importFolder(f, workspaceId) {
console.log('IMPORTING FOLDER', f._id, f.name, JSON.stringify(f, null, 2));
return {
id: f._id,
createdAt: new Date(f.created ?? Date.now()).toISOString().replace('Z', ''),
updatedAt: new Date(f.updated ?? Date.now()).toISOString().replace('Z', ''),
folderId: f.parentId === workspaceId ? null : f.parentId,
workspaceId,
model: 'folder',
name: f.name,
};
}

View File

@@ -0,0 +1,60 @@
import { convertSyntax } from '../helpers/variables.js';
/**
* Import an Insomnia request object.
* @param {Object} r - The request object to import.
* @param workspaceId - The workspace ID to use for the request.
* @param {number} sortPriority - The sort priority to use for the request.
*/
export function importRequest(r, workspaceId, sortPriority = 0) {
console.log('IMPORTING REQUEST', r._id, r.name, JSON.stringify(r, null, 2));
let bodyType = null;
let body = null;
if (r.body?.mimeType === 'application/graphql') {
bodyType = 'graphql';
body = convertSyntax(r.body.text);
} else if (r.body?.mimeType === 'application/json') {
bodyType = 'application/json';
body = convertSyntax(r.body.text);
}
let authenticationType = null;
let authentication = {};
if (r.authentication.type === 'bearer') {
authenticationType = 'bearer';
authentication = {
token: convertSyntax(r.authentication.token),
};
} else if (r.authentication.type === 'basic') {
authenticationType = 'basic';
authentication = {
username: convertSyntax(r.authentication.username),
password: convertSyntax(r.authentication.password),
};
}
return {
id: r._id,
createdAt: new Date(r.created ?? Date.now()).toISOString().replace('Z', ''),
updatedAt: new Date(r.updated ?? Date.now()).toISOString().replace('Z', ''),
workspaceId,
folderId: r.parentId === workspaceId ? null : r.parentId,
model: 'http_request',
sortPriority,
name: r.name,
url: convertSyntax(r.url),
body,
bodyType,
authentication,
authenticationType,
method: r.method,
headers: (r.headers ?? [])
.map(({ name, value, disabled }) => ({
enabled: !disabled,
name,
value,
}))
.filter(({ name, value }) => name !== '' || value !== ''),
};
}

View File

@@ -0,0 +1,76 @@
import { importEnvironment } from './importers/environment.js';
import { importRequest } from './importers/request.js';
import {
isEnvironment,
isJSObject,
isRequest,
isRequestGroup,
isWorkspace,
} from './helpers/types.js';
import { parseVariables } from './helpers/variables.js';
import { importFolder } from './importers/folder.js';
export function pluginHookImport(contents) {
console.log('RUNNING INSOMNIA');
let parsed;
try {
parsed = JSON.parse(contents);
} catch (e) {
return;
}
if (!isJSObject(parsed)) return;
if (!Array.isArray(parsed.resources)) return;
const resources = {
workspaces: [],
requests: [],
environments: [],
folders: [],
};
// Import workspaces
const workspacesToImport = parsed.resources.filter(isWorkspace);
for (const workspaceToImport of workspacesToImport) {
const baseEnvironment = parsed.resources.find(
(r) => isEnvironment(r) && r.parentId === workspaceToImport._id,
);
resources.workspaces.push({
id: workspaceToImport._id,
createdAt: new Date(workspacesToImport.created ?? Date.now()).toISOString().replace('Z', ''),
updatedAt: new Date(workspacesToImport.updated ?? Date.now()).toISOString().replace('Z', ''),
model: 'workspace',
name: workspaceToImport.name,
variables: baseEnvironment ? parseVariables(baseEnvironment.data) : [],
});
const environmentsToImport = parsed.resources.filter(
(r) => isEnvironment(r) && r.parentId === baseEnvironment?._id,
);
resources.environments.push(
...environmentsToImport.map((r) => importEnvironment(r, workspaceToImport._id)),
);
const nextFolder = (parentId) => {
const children = parsed.resources.filter((r) => r.parentId === parentId);
let sortPriority = 0;
for (const child of children) {
if (isRequestGroup(child)) {
resources.folders.push(importFolder(child, workspaceToImport._id));
nextFolder(child._id);
} else if (isRequest(child)) {
resources.requests.push(importRequest(child, workspaceToImport._id, sortPriority++));
}
}
};
// Import folders
nextFolder(workspaceToImport._id);
}
// Filter out any `null` values
resources.requests = resources.requests.filter(Boolean);
resources.environments = resources.environments.filter(Boolean);
resources.workspaces = resources.workspaces.filter(Boolean);
return { resources };
}

View File

@@ -0,0 +1,13 @@
import { resolve } from 'path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.js'),
fileName: 'index',
formats: ['es'],
},
outDir: resolve(__dirname, '../../src-tauri/plugins/importer-insomnia'),
},
});

View File

@@ -0,0 +1,12 @@
{
"name": "importer-postman",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "importer-postman",
"version": "0.0.1"
}
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "importer-postman",
"version": "0.0.1"
}

View File

@@ -0,0 +1,223 @@
import { Environment, Folder, HttpRequest, Workspace } from '../../../src-web/lib/models';
const POSTMAN_2_1_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.1.0/collection.json';
const POSTMAN_2_0_0_SCHEMA = 'https://schema.getpostman.com/json/collection/v2.0.0/collection.json';
const VALID_SCHEMAS = [POSTMAN_2_0_0_SCHEMA, POSTMAN_2_1_0_SCHEMA];
type AtLeast<T, K extends keyof T> = Partial<T> & Pick<T, K>;
interface ExportResources {
workspaces: AtLeast<Workspace, 'name' | 'id' | 'model'>[];
environments: AtLeast<Environment, 'name' | 'id' | 'model' | 'workspaceId'>[];
requests: AtLeast<HttpRequest, 'name' | 'id' | 'model' | 'workspaceId'>[];
folders: AtLeast<Folder, 'name' | 'id' | 'model' | 'workspaceId'>[];
}
export function pluginHookImport(contents: string): { resources: ExportResources } | undefined {
const root = parseJSONToRecord(contents);
if (root == null) return;
const info = toRecord(root.info);
const isValidSchema = VALID_SCHEMAS.includes(info.schema);
if (!isValidSchema || !Array.isArray(root.item)) {
return;
}
const exportResources: ExportResources = {
workspaces: [],
environments: [],
requests: [],
folders: [],
};
const workspace: ExportResources['workspaces'][0] = {
model: 'workspace',
id: generateId('wk'),
name: info.name || 'Postman Import',
description: info.description || '',
};
exportResources.workspaces.push(workspace);
const importItem = (v: Record<string, any>, folderId: string | null = null) => {
if (typeof v.name === 'string' && Array.isArray(v.item)) {
const folder: ExportResources['folders'][0] = {
model: 'folder',
workspaceId: workspace.id,
id: generateId('fl'),
name: v.name,
folderId,
};
exportResources.folders.push(folder);
for (const child of v.item) {
importItem(child, folder.id);
}
} else if (typeof v.name === 'string' && 'request' in v) {
const r = toRecord(v.request);
const bodyPatch = importBody(r.body);
const authPatch = importAuth(r.auth);
const request: ExportResources['requests'][0] = {
model: 'http_request',
id: generateId('rq'),
workspaceId: workspace.id,
folderId,
name: v.name,
method: r.method || 'GET',
url: typeof r.url === 'string' ? r.url : toRecord(r.url).raw,
body: bodyPatch.body,
bodyType: bodyPatch.bodyType,
authentication: authPatch.authentication,
authenticationType: authPatch.authenticationType,
headers: [
...bodyPatch.headers,
...authPatch.headers,
...toArray(r.header).map((h) => {
return {
name: h.key,
value: h.value,
enabled: !h.disabled,
};
}),
],
};
exportResources.requests.push(request);
} else {
console.log('Unknown item', v, folderId);
}
};
for (const item of root.item) {
importItem(item);
}
return { resources: convertTemplateSyntax(exportResources) };
}
function importAuth(
rawAuth: any,
): Pick<HttpRequest, 'authentication' | 'authenticationType' | 'headers'> {
const auth = toRecord(rawAuth);
if ('basic' in auth) {
return {
headers: [],
authenticationType: 'basic',
authentication: {
username: auth.basic.username || '',
password: auth.basic.password || '',
},
};
} else {
// TODO: support other auth types
return { headers: [], authenticationType: null, authentication: {} };
}
}
function importBody(rawBody: any): Pick<HttpRequest, 'body' | 'bodyType' | 'headers'> {
const body = toRecord(rawBody);
if ('graphql' in body) {
return {
headers: [
{
name: 'Content-Type',
value: 'application/json',
enabled: true,
},
],
bodyType: 'graphql',
body: {
text: JSON.stringify(
{ query: body.graphql.query, variables: parseJSONToRecord(body.graphql.variables) },
null,
2,
),
},
};
} else if ('urlencoded' in body) {
return {
headers: [
{
name: 'Content-Type',
value: 'application/x-www-form-urlencoded',
enabled: true,
},
],
bodyType: 'application/x-www-form-urlencoded',
body: {
form: toArray(body.urlencoded).map((f) => ({
enabled: !f.disabled,
name: f.key ?? '',
value: f.value ?? '',
})),
},
};
} else if ('formdata' in body) {
return {
headers: [
{
name: 'Content-Type',
value: 'multipart/form-data',
enabled: true,
},
],
bodyType: 'multipart/form-data',
body: {
form: toArray(body.formdata).map((f) =>
f.src != null
? {
enabled: !f.disabled,
name: f.key ?? '',
file: f.src ?? '',
}
: {
enabled: !f.disabled,
name: f.key ?? '',
value: f.value ?? '',
},
),
},
};
} else {
// TODO: support other body types
return { headers: [], bodyType: null, body: {} };
}
}
function parseJSONToRecord(jsonStr: string): Record<string, any> | null {
try {
return toRecord(JSON.parse(jsonStr));
} catch (err) {}
return null;
}
function toRecord(value: any): Record<string, any> {
if (Object.prototype.toString.call(value) === '[object Object]') return value;
else return {};
}
function toArray(value: any): any[] {
if (Object.prototype.toString.call(value) === '[object Array]') return value;
else return [];
}
/** Recursively render all nested object properties */
function convertTemplateSyntax<T>(obj: T): T {
if (typeof obj === 'string') {
return obj.replace(/{{\s*(_\.)?([^}]+)\s*}}/g, '${[$2]}') as T;
} else if (Array.isArray(obj) && obj != null) {
return obj.map(convertTemplateSyntax) as T;
} else if (typeof obj === 'object' && obj != null) {
return Object.fromEntries(
Object.entries(obj).map(([k, v]) => [k, convertTemplateSyntax(v)]),
) as T;
} else {
return obj;
}
}
function generateId(prefix: 'wk' | 'rq' | 'fl'): string {
const alphabet = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
let id = `${prefix}_`;
for (let i = 0; i < 10; i++) {
id += alphabet[Math.floor(Math.random() * alphabet.length)];
}
return id;
}

View File

@@ -0,0 +1,23 @@
{
"compilerOptions": {
"target": "ESNext",
"useDefineForClassFields": true,
"module": "ESNext",
"lib": [
"ESNext",
],
"skipLibCheck": true,
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": [
"./src"
]
}

View File

@@ -0,0 +1,13 @@
import { resolve } from 'path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.ts'),
fileName: 'index',
formats: ['es'],
},
outDir: resolve(__dirname, '../../src-tauri/plugins/importer-postman'),
},
});

12
plugins/importer-yaak/package-lock.json generated Normal file
View File

@@ -0,0 +1,12 @@
{
"name": "importer-yaak",
"version": "0.0.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "importer-yaak",
"version": "0.0.1"
}
}
}

View File

@@ -0,0 +1,4 @@
{
"name": "importer-yaak",
"version": "0.0.1"
}

View File

@@ -0,0 +1,32 @@
export function pluginHookImport(contents) {
let parsed;
try {
parsed = JSON.parse(contents);
} catch (err) {
return undefined;
}
if (!isJSObject(parsed)) {
return undefined;
}
if (!('yaakSchema' in parsed)) {
return;
}
// Migrate v1 to v2 -- changes requests to httpRequests
if (parsed.yaakSchema === 1) {
parsed.resources.httpRequests = parsed.resources.requests;
parsed.yaakSchema = 2;
}
if (parsed.yaakSchema === 2) {
return { resources: parsed.resources }; // Should already be in the correct format
}
return undefined;
}
export function isJSObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]';
}

View File

@@ -0,0 +1,13 @@
import { resolve } from 'path';
import { defineConfig } from 'vite';
export default defineConfig({
build: {
lib: {
entry: resolve(__dirname, 'src/index.js'),
fileName: 'index',
formats: ['es'],
},
outDir: resolve(__dirname, '../../src-tauri/plugins/importer-yaak'),
},
});

View File

@@ -1,11 +0,0 @@
syntax = "proto3";
package yaak.plugins.runtime;
service PluginRuntime {
rpc EventStream (stream EventStreamEvent) returns (stream EventStreamEvent);
}
message EventStreamEvent {
string event = 1;
}

View File

@@ -1,7 +1 @@
edition = "2024"
# Widths
chain_width = 100
max_width = 100
single_line_if_else_max_width = 100
fn_call_width = 100
edition = "2018"

1
scripts/.gitignore vendored
View File

@@ -1 +0,0 @@
tmp-*

View File

@@ -1,15 +0,0 @@
const path = require('path');
const fs = require('fs');
const version = process.env.YAAK_VERSION?.replace('v', '');
if (!version) {
throw new Error('YAAK_VERSION environment variable not set')
}
const tauriConfigPath = path.join(__dirname, '../src-tauri/tauri.conf.json');
const tauriConfig = JSON.parse(fs.readFileSync(tauriConfigPath, 'utf8'));
tauriConfig.version = version;
console.log('Writing version ' + version + ' to ' + tauriConfigPath)
fs.writeFileSync(tauriConfigPath, JSON.stringify(tauriConfig, null, 2));

View File

@@ -1,87 +0,0 @@
const path = require('node:path');
const decompress = require('decompress');
const Downloader = require('nodejs-file-downloader');
const { rmSync, cpSync, mkdirSync, existsSync } = require('node:fs');
const { execSync } = require('node:child_process');
const NODE_VERSION = 'v22.9.0';
// `${process.platform}_${process.arch}`
const MAC_ARM = 'darwin_arm64';
const MAC_X64 = 'darwin_x64';
const LNX_ARM = 'linux_arm64';
const LNX_X64 = 'linux_x64';
const WIN_X64 = 'win32_x64';
const URL_MAP = {
[MAC_ARM]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-darwin-arm64.tar.gz`,
[MAC_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-darwin-x64.tar.gz`,
[LNX_ARM]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-linux-arm64.tar.gz`,
[LNX_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-linux-x64.tar.gz`,
[WIN_X64]: `https://nodejs.org/download/release/${NODE_VERSION}/node-${NODE_VERSION}-win-x64.zip`,
};
const SRC_BIN_MAP = {
[MAC_ARM]: `node-${NODE_VERSION}-darwin-arm64/bin/node`,
[MAC_X64]: `node-${NODE_VERSION}-darwin-x64/bin/node`,
[LNX_ARM]: `node-${NODE_VERSION}-linux-arm64/bin/node`,
[LNX_X64]: `node-${NODE_VERSION}-linux-x64/bin/node`,
[WIN_X64]: `node-${NODE_VERSION}-win-x64/node.exe`,
};
const DST_BIN_MAP = {
[MAC_ARM]: 'yaaknode-aarch64-apple-darwin',
[MAC_X64]: 'yaaknode-x86_64-apple-darwin',
[LNX_ARM]: 'yaaknode-aarch64-unknown-linux-gnu',
[LNX_X64]: 'yaaknode-x86_64-unknown-linux-gnu',
[WIN_X64]: 'yaaknode-x86_64-pc-windows-msvc.exe',
};
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
const destDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'node');
const binDest = path.join(destDir, DST_BIN_MAP[key]);
console.log(`Vendoring NodeJS ${NODE_VERSION} for ${key}`);
if (existsSync(binDest) && tryExecSync(`${binDest} --version`).trim() === NODE_VERSION) {
console.log('NodeJS already vendored');
return;
}
rmSync(destDir, { recursive: true, force: true });
mkdirSync(destDir, { recursive: true });
const url = URL_MAP[key];
const tmpDir = path.join(__dirname, 'tmp-node');
rmSync(tmpDir, { recursive: true, force: true });
(async function () {
// Download GitHub release artifact
console.log('Downloading NodeJS at', url);
const { filePath } = await new Downloader({
url,
directory: tmpDir,
timeout: 1000 * 60 * 2,
}).download();
// Decompress to the same directory
await decompress(filePath, tmpDir, {});
// Copy binary
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
cpSync(binSrc, binDest);
rmSync(tmpDir, { recursive: true, force: true });
console.log('Downloaded NodeJS to', binDest);
})().catch((err) => {
console.log('Script failed:', err);
process.exit(1);
});
function tryExecSync(cmd) {
try {
return execSync(cmd).toString('utf-8');
} catch (_) {
return '';
}
}

View File

@@ -1,25 +0,0 @@
const { readdirSync, cpSync } = require('node:fs');
const path = require('node:path');
const { execSync } = require('node:child_process');
const pluginsDir = process.env.YAAK_PLUGINS_DIR;
if (!pluginsDir) {
console.log('Skipping bundled plugins build because YAAK_PLUGINS_DIR is not set');
return;
}
console.log('Installing Yaak plugins dependencies', pluginsDir);
execSync('npm ci', { cwd: pluginsDir });
console.log('Building Yaak plugins', pluginsDir);
execSync('npm run build', { cwd: pluginsDir });
console.log('Copying Yaak plugins to', pluginsDir);
const pluginsRoot = path.join(pluginsDir, 'plugins');
for (const name of readdirSync(pluginsRoot)) {
const dir = path.join(pluginsRoot, name);
if (name.startsWith('.')) continue;
const destDir = path.join(__dirname, '../src-tauri/vendored/plugins/', name);
console.log(`Copying ${name} to ${destDir}`);
cpSync(path.join(dir, 'package.json'), path.join(destDir, 'package.json'));
cpSync(path.join(dir, 'build/index.js'), path.join(destDir, 'build/index.js'));
}

View File

@@ -1,88 +0,0 @@
const decompress = require('decompress');
const Downloader = require('nodejs-file-downloader');
const path = require('node:path');
const { rmSync, mkdirSync, cpSync, existsSync, statSync, chmodSync } = require('node:fs');
const { execSync } = require('node:child_process');
const VERSION = '28.3';
// `${process.platform}_${process.arch}`
const MAC_ARM = 'darwin_arm64';
const MAC_X64 = 'darwin_x64';
const LNX_ARM = 'linux_arm64';
const LNX_X64 = 'linux_x64';
const WIN_X64 = 'win32_x64';
const URL_MAP = {
[MAC_ARM]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-osx-aarch_64.zip`,
[MAC_X64]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-osx-x86_64.zip`,
[LNX_ARM]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-linux-aarch_64.zip`,
[LNX_X64]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-linux-x86_64.zip`,
[WIN_X64]: `https://github.com/protocolbuffers/protobuf/releases/download/v${VERSION}/protoc-${VERSION}-win64.zip`,
};
const SRC_BIN_MAP = {
[MAC_ARM]: 'bin/protoc',
[MAC_X64]: 'bin/protoc',
[LNX_ARM]: 'bin/protoc',
[LNX_X64]: 'bin/protoc',
[WIN_X64]: 'bin/protoc.exe',
};
const DST_BIN_MAP = {
[MAC_ARM]: 'yaakprotoc-aarch64-apple-darwin',
[MAC_X64]: 'yaakprotoc-x86_64-apple-darwin',
[LNX_ARM]: 'yaakprotoc-aarch64-unknown-linux-gnu',
[LNX_X64]: 'yaakprotoc-x86_64-unknown-linux-gnu',
[WIN_X64]: 'yaakprotoc-x86_64-pc-windows-msvc.exe',
};
const dstDir = path.join(__dirname, `..`, 'src-tauri', 'vendored', 'protoc');
const key = `${process.platform}_${process.env.YAAK_TARGET_ARCH ?? process.arch}`;
console.log(`Vendoring protoc ${VERSION} for ${key}`);
const url = URL_MAP[key];
const tmpDir = path.join(__dirname, 'tmp-protoc');
const binSrc = path.join(tmpDir, SRC_BIN_MAP[key]);
const binDst = path.join(dstDir, DST_BIN_MAP[key]);
if (existsSync(binDst) && tryExecSync(`${binDst} --version`).trim().includes(VERSION)) {
console.log('Protoc already vendored');
return;
}
rmSync(tmpDir, { recursive: true, force: true });
rmSync(dstDir, { recursive: true, force: true });
mkdirSync(dstDir, { recursive: true });
(async function () {
// Download GitHub release artifact
const { filePath } = await new Downloader({ url, directory: tmpDir }).download();
// Decompress to the same directory
await decompress(filePath, tmpDir, {});
// Copy binary
cpSync(binSrc, binDst);
// Copy other files
const includeSrc = path.join(tmpDir, 'include');
const includeDst = path.join(dstDir, 'include');
cpSync(includeSrc, includeDst, { recursive: true });
rmSync(tmpDir, { recursive: true, force: true });
// Make binary writable, so we can sign it during release
const stat = statSync(binDst);
const newMode = stat.mode | 0o200;
chmodSync(binDst, newMode);
console.log('Downloaded protoc to', binDst);
})().catch((err) => console.log('Script failed:', err));
function tryExecSync(cmd) {
try {
return execSync(cmd).toString('utf-8');
} catch (_) {
return '';
}
}

View File

@@ -1,11 +1,4 @@
# Generated by Cargo
# will have compiled files and executables
target/
/target/
vendored/*
!vendored/plugins
gen/*
**/permissions/autogenerated
**/permissions/schemas

View File

@@ -0,0 +1,50 @@
{
"db_name": "SQLite",
"query": "\n SELECT model, created_at, updated_at, namespace, key, value\n FROM key_values\n WHERE namespace = ? AND key = ?\n ",
"describe": {
"columns": [
{
"name": "model",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "created_at",
"ordinal": 1,
"type_info": "Datetime"
},
{
"name": "updated_at",
"ordinal": 2,
"type_info": "Datetime"
},
{
"name": "namespace",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "key",
"ordinal": 4,
"type_info": "Text"
},
{
"name": "value",
"ordinal": 5,
"type_info": "Text"
}
],
"parameters": {
"Right": 2
},
"nullable": [
false,
false,
false,
false,
false,
false
]
},
"hash": "06aaf8f4a17566f1d25da2a60f0baf4b5fc28c3cf0c001a84e25edf9eab3c7e3"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "\n DELETE FROM http_responses\n WHERE id = ?\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 1
},
"nullable": []
},
"hash": "07d1a1c7b4f3d9625a766e60fd57bb779b71dae30e5bbce34885a911a5a42428"
}

View File

@@ -0,0 +1,116 @@
{
"db_name": "SQLite",
"query": "\n SELECT\n id, model, workspace_id, request_id, updated_at, created_at, url, status,\n status_reason, content_length, body_path, elapsed, elapsed_headers, error,\n version, remote_addr,\n headers AS \"headers!: sqlx::types::Json<Vec<HttpResponseHeader>>\"\n FROM http_responses\n WHERE id = ?\n ",
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "model",
"ordinal": 1,
"type_info": "Text"
},
{
"name": "workspace_id",
"ordinal": 2,
"type_info": "Text"
},
{
"name": "request_id",
"ordinal": 3,
"type_info": "Text"
},
{
"name": "updated_at",
"ordinal": 4,
"type_info": "Datetime"
},
{
"name": "created_at",
"ordinal": 5,
"type_info": "Datetime"
},
{
"name": "url",
"ordinal": 6,
"type_info": "Text"
},
{
"name": "status",
"ordinal": 7,
"type_info": "Int64"
},
{
"name": "status_reason",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "content_length",
"ordinal": 9,
"type_info": "Int64"
},
{
"name": "body_path",
"ordinal": 10,
"type_info": "Text"
},
{
"name": "elapsed",
"ordinal": 11,
"type_info": "Int64"
},
{
"name": "elapsed_headers",
"ordinal": 12,
"type_info": "Int64"
},
{
"name": "error",
"ordinal": 13,
"type_info": "Text"
},
{
"name": "version",
"ordinal": 14,
"type_info": "Text"
},
{
"name": "remote_addr",
"ordinal": 15,
"type_info": "Text"
},
{
"name": "headers!: sqlx::types::Json<Vec<HttpResponseHeader>>",
"ordinal": 16,
"type_info": "Text"
}
],
"parameters": {
"Right": 1
},
"nullable": [
false,
false,
false,
false,
false,
false,
false,
false,
true,
true,
true,
false,
false,
true,
true,
true,
false
]
},
"hash": "0fa6b56f8c996d14908a56928674b4b35af5fa36f63dc48b9b66ee6dfde78976"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO http_requests (\n id, workspace_id, folder_id, name, url, url_parameters, method, body, body_type,\n authentication, authentication_type, headers, sort_priority\n )\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n folder_id = excluded.folder_id,\n method = excluded.method,\n headers = excluded.headers,\n body = excluded.body,\n body_type = excluded.body_type,\n authentication = excluded.authentication,\n authentication_type = excluded.authentication_type,\n url = excluded.url,\n url_parameters = excluded.url_parameters,\n sort_priority = excluded.sort_priority\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 13
},
"nullable": []
},
"hash": "11394af12419cca3be3a26dff9275514ea2a44504e3c7a568a9578c64b5713d1"
}

View File

@@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "\n INSERT INTO workspaces (\n id, name, description, variables, setting_request_timeout,\n setting_follow_redirects, setting_validate_certificates\n )\n VALUES (?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (id) DO UPDATE SET\n updated_at = CURRENT_TIMESTAMP,\n name = excluded.name,\n description = excluded.description,\n variables = excluded.variables,\n setting_request_timeout = excluded.setting_request_timeout,\n setting_follow_redirects = excluded.setting_follow_redirects,\n setting_validate_certificates = excluded.setting_validate_certificates\n ",
"describe": {
"columns": [],
"parameters": {
"Right": 7
},
"nullable": []
},
"hash": "12b265491d1ebba19e1ce8a660e458ffbcd8c0850aef16ba1f70e358623ac66a"
}

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