state.svelte.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. import { invoke } from "@tauri-apps/api/core";
  2. import type {
  3. Workspace,
  4. WorkspaceEntryBase,
  5. RequestBody,
  6. WorkspaceEntry,
  7. WorkspaceEnvironment,
  8. EnvVariable,
  9. } from "./types";
  10. export type WorkspaceState = {
  11. /**
  12. * Currently selected workspace.
  13. */
  14. workspace: Workspace | null;
  15. /**
  16. * Currently selected workspace entry.
  17. */
  18. entry: WorkspaceEntry | null;
  19. /**
  20. * Workspace root entries.
  21. */
  22. roots: number[];
  23. /**
  24. * Workspace entry parent => children mappings.
  25. */
  26. children: Record<number, number[]>;
  27. /**
  28. * All workspace entries.
  29. */
  30. indexes: Record<number, WorkspaceEntry>;
  31. /**
  32. * Currently selected workspace environments.
  33. */
  34. environments: WorkspaceEnvironment[];
  35. /**
  36. * Currently selected environment.
  37. */
  38. environment: WorkspaceEnvironment | null;
  39. };
  40. export const state: WorkspaceState = $state({
  41. workspace: null,
  42. entry: null,
  43. roots: [],
  44. children: {},
  45. indexes: {},
  46. environments: [],
  47. environment: null,
  48. });
  49. const index = (entry: WorkspaceEntry) => {
  50. console.log("indexing", entry);
  51. state.indexes[entry.id] = entry;
  52. if (entry.parent_id !== null) {
  53. if (state.children[entry.parent_id]) {
  54. state.children[entry.parent_id].push(entry.id);
  55. } else {
  56. state.children[entry.parent_id] = [entry.id];
  57. }
  58. } else {
  59. state.roots.push(entry.id);
  60. }
  61. };
  62. function reset() {
  63. state.children = {};
  64. state.indexes = {};
  65. state.roots = [];
  66. state.entry = null;
  67. state.environment = null;
  68. state.environments = [];
  69. }
  70. export function selectEnvironment(id: number | null) {
  71. if (id === null) {
  72. state.environment = null;
  73. return;
  74. }
  75. console.debug("selecting environment:", state.environments[id]);
  76. state.environment = state.environments.find((e) => e.id === id) ?? null;
  77. }
  78. export function selectWorkspace(ws: Workspace) {
  79. console.debug("selecting workspace:", ws.name);
  80. state.workspace = ws;
  81. }
  82. export function selectEntry(id: number) {
  83. console.log("selecting entry:", id);
  84. state.entry = state.indexes[id];
  85. if (state.entry.parent_id !== null) {
  86. let parent = state.indexes[state.entry.parent_id];
  87. while (parent) {
  88. parent.open = true;
  89. if (parent.parent_id === null) {
  90. break;
  91. }
  92. parent = state.indexes[parent.parent_id];
  93. }
  94. }
  95. }
  96. // COMMANDS
  97. export async function createWorkspace(name: string): Promise<Workspace> {
  98. return invoke<Workspace>("create_workspace", { name });
  99. }
  100. export async function listWorkspaces(): Promise<Workspace[]> {
  101. return invoke<Workspace[]>("list_workspaces");
  102. }
  103. export async function loadWorkspace(ws: Workspace) {
  104. reset();
  105. state.workspace = ws;
  106. const entries = await invoke<WorkspaceEntryResponse[]>(
  107. "get_workspace_entries",
  108. {
  109. id: state.workspace.id,
  110. },
  111. );
  112. for (const entry of entries) {
  113. if (entry.type === "Request") {
  114. index({
  115. ...entry.data.entry,
  116. method: entry.data.method,
  117. url: entry.data.url,
  118. headers: entry.data.headers,
  119. body: entry.data.body,
  120. });
  121. } else {
  122. index(entry.data);
  123. }
  124. }
  125. await loadEnvironments(state.workspace.id);
  126. }
  127. export function createRequest(parentId?: number) {
  128. if (state.workspace == null) {
  129. console.warn("create workspace request called with no active workspace");
  130. return;
  131. }
  132. const data = {
  133. Request: {
  134. name: "",
  135. workspace_id: state.workspace.id,
  136. parent_id: parentId,
  137. method: "GET",
  138. url: "",
  139. },
  140. };
  141. invoke<WorkspaceEntryBase>("create_workspace_entry", {
  142. data,
  143. }).then((entry) => {
  144. index({
  145. ...entry,
  146. method: data.Request.method,
  147. url: data.Request.url,
  148. body: null,
  149. headers: {},
  150. });
  151. console.log("request created:", entry);
  152. });
  153. }
  154. export function createCollection(parentId?: number) {
  155. if (state.workspace == null) {
  156. console.warn("create workspace request called with no active workspace");
  157. return;
  158. }
  159. const data = {
  160. Collection: {
  161. name: "",
  162. workspace_id: state.workspace.id,
  163. parent_id: parentId,
  164. },
  165. };
  166. invoke<WorkspaceEntryBase>("create_workspace_entry", {
  167. data,
  168. }).then((entry) => {
  169. index(entry);
  170. console.log("collection created:", entry);
  171. });
  172. }
  173. export async function loadEnvironments(workspaceId: number) {
  174. state.environments = await invoke<WorkspaceEnvironment[]>(
  175. "list_environments",
  176. { workspaceId },
  177. );
  178. }
  179. export async function createEnvironment(workspaceId: number, name: string) {
  180. console.debug("creating environment in", workspaceId);
  181. const env = await invoke<WorkspaceEnvironment>("create_env", {
  182. workspaceId,
  183. name,
  184. });
  185. state.environment = env;
  186. state.environments.push(state.environment);
  187. }
  188. export async function updateEnvironment() {
  189. if (!state.environment) {
  190. console.warn("attempted to persist null env");
  191. return;
  192. }
  193. console.debug("updating environment", state.environment);
  194. await invoke("update_env", {
  195. id: state.environment.id,
  196. name: state.environment.name,
  197. });
  198. }
  199. export async function insertEnvVariable(
  200. workspaceId: number,
  201. envId: number,
  202. name: string = "",
  203. value: string = "",
  204. secret: boolean = false,
  205. ) {
  206. const v = await invoke<EnvVariable>("insert_env_var", {
  207. workspaceId,
  208. envId,
  209. name,
  210. value,
  211. secret,
  212. });
  213. state.environment?.variables.push(v);
  214. }
  215. export async function updateEnvVariable(v: EnvVariable) {
  216. if (v.name.length === 0 && v.value.length === 0) {
  217. console.debug("deleting var:", v);
  218. return deleteEnvVariable(v.id);
  219. }
  220. console.debug("updating var:", v);
  221. return invoke("update_env_var", {
  222. id: v.id,
  223. name: v.name,
  224. value: v.value,
  225. secret: v.secret,
  226. });
  227. }
  228. export async function deleteEnvVariable(id: number) {
  229. await invoke("delete_env_var", { id });
  230. state.environment!!.variables = state.environment!!.variables.filter(
  231. (v) => v.id !== id,
  232. );
  233. }
  234. type WorkspaceEntryResponse =
  235. | {
  236. type: "Collection";
  237. data: WorkspaceEntryBase;
  238. }
  239. | {
  240. type: "Request";
  241. data: WorkspaceRequestResponse;
  242. };
  243. type WorkspaceRequestResponse = {
  244. entry: WorkspaceEntryBase;
  245. method: string;
  246. url: string;
  247. body: RequestBody | null;
  248. headers: { [key: string]: string };
  249. };