collections.ts 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943
  1. import { pluck } from "rxjs/operators"
  2. import DispatchingStore, { defineDispatchers } from "./DispatchingStore"
  3. import { getRESTSaveContext, setRESTSaveContext } from "./RESTSession"
  4. import {
  5. HoppRESTRequest,
  6. translateToNewRequest,
  7. } from "~/helpers/types/HoppRESTRequest"
  8. import {
  9. HoppGQLRequest,
  10. translateToGQLRequest,
  11. } from "~/helpers/types/HoppGQLRequest"
  12. export interface Collection<T extends HoppRESTRequest | HoppGQLRequest> {
  13. v: number
  14. name: string
  15. folders: Collection<T>[]
  16. requests: T[]
  17. id?: string // For Firestore ID
  18. }
  19. const defaultRESTCollectionState = {
  20. state: [
  21. makeCollection<HoppRESTRequest>({
  22. name: "My Collection",
  23. folders: [],
  24. requests: [],
  25. }),
  26. ],
  27. }
  28. const defaultGraphqlCollectionState = {
  29. state: [
  30. makeCollection<HoppGQLRequest>({
  31. name: "My GraphQL Collection",
  32. folders: [],
  33. requests: [],
  34. }),
  35. ],
  36. }
  37. export function makeCollection<T extends HoppRESTRequest | HoppGQLRequest>(
  38. x: Omit<Collection<T>, "v">
  39. ): Collection<T> {
  40. return {
  41. v: 1,
  42. ...x,
  43. }
  44. }
  45. export function translateToNewRESTCollection(
  46. x: any
  47. ): Collection<HoppRESTRequest> {
  48. if (x.v && x.v === 1) return x
  49. // Legacy
  50. const name = x.name ?? "Untitled"
  51. const folders = (x.folders ?? []).map(translateToNewRESTCollection)
  52. const requests = (x.requests ?? []).map(translateToNewRequest)
  53. const obj = makeCollection<HoppRESTRequest>({
  54. name,
  55. folders,
  56. requests,
  57. })
  58. if (x.id) obj.id = x.id
  59. return obj
  60. }
  61. export function translateToNewGQLCollection(
  62. x: any
  63. ): Collection<HoppGQLRequest> {
  64. if (x.v && x.v === 1) return x
  65. // Legacy
  66. const name = x.name ?? "Untitled"
  67. const folders = (x.folders ?? []).map(translateToNewGQLCollection)
  68. const requests = (x.requests ?? []).map(translateToGQLRequest)
  69. const obj = makeCollection<HoppGQLRequest>({
  70. name,
  71. folders,
  72. requests,
  73. })
  74. if (x.id) obj.id = x.id
  75. return obj
  76. }
  77. type RESTCollectionStoreType = typeof defaultRESTCollectionState
  78. type GraphqlCollectionStoreType = typeof defaultGraphqlCollectionState
  79. function navigateToFolderWithIndexPath(
  80. collections: Collection<HoppRESTRequest | HoppGQLRequest>[],
  81. indexPaths: number[]
  82. ) {
  83. if (indexPaths.length === 0) return null
  84. let target = collections[indexPaths.shift() as number]
  85. while (indexPaths.length > 0)
  86. target = target.folders[indexPaths.shift() as number]
  87. return target !== undefined ? target : null
  88. }
  89. const restCollectionDispatchers = defineDispatchers({
  90. setCollections(
  91. _: RESTCollectionStoreType,
  92. { entries }: { entries: Collection<HoppRESTRequest>[] }
  93. ) {
  94. return {
  95. state: entries,
  96. }
  97. },
  98. appendCollections(
  99. { state }: RESTCollectionStoreType,
  100. { entries }: { entries: Collection<HoppRESTRequest>[] }
  101. ) {
  102. return {
  103. state: [...state, ...entries],
  104. }
  105. },
  106. addCollection(
  107. { state }: RESTCollectionStoreType,
  108. { collection }: { collection: Collection<any> }
  109. ) {
  110. return {
  111. state: [...state, collection],
  112. }
  113. },
  114. removeCollection(
  115. { state }: RESTCollectionStoreType,
  116. { collectionIndex }: { collectionIndex: number }
  117. ) {
  118. return {
  119. state: (state as any).filter(
  120. (_: any, i: number) => i !== collectionIndex
  121. ),
  122. }
  123. },
  124. editCollection(
  125. { state }: RESTCollectionStoreType,
  126. {
  127. collectionIndex,
  128. collection,
  129. }: { collectionIndex: number; collection: Collection<any> }
  130. ) {
  131. return {
  132. state: state.map((col, index) =>
  133. index === collectionIndex ? collection : col
  134. ),
  135. }
  136. },
  137. addFolder(
  138. { state }: RESTCollectionStoreType,
  139. { name, path }: { name: string; path: string }
  140. ) {
  141. const newFolder: Collection<HoppRESTRequest> = makeCollection({
  142. name,
  143. folders: [],
  144. requests: [],
  145. })
  146. const newState = state
  147. const indexPaths = path.split("/").map((x) => parseInt(x))
  148. const target = navigateToFolderWithIndexPath(newState, indexPaths)
  149. if (target === null) {
  150. console.log(`Could not parse path '${path}'. Ignoring add folder request`)
  151. return {}
  152. }
  153. target.folders.push(newFolder)
  154. return {
  155. state: newState,
  156. }
  157. },
  158. editFolder(
  159. { state }: RESTCollectionStoreType,
  160. { path, folder }: { path: string; folder: string }
  161. ) {
  162. const newState = state
  163. const indexPaths = path.split("/").map((x) => parseInt(x))
  164. const target = navigateToFolderWithIndexPath(newState, indexPaths)
  165. if (target === null) {
  166. console.log(
  167. `Could not parse path '${path}'. Ignoring edit folder request`
  168. )
  169. return {}
  170. }
  171. Object.assign(target, folder)
  172. return {
  173. state: newState,
  174. }
  175. },
  176. removeFolder({ state }: RESTCollectionStoreType, { path }: { path: string }) {
  177. const newState = state
  178. const indexPaths = path.split("/").map((x) => parseInt(x))
  179. if (indexPaths.length === 0) {
  180. console.log(
  181. "Given path too short. If this is a collection, use removeCollection dispatcher instead. Skipping request."
  182. )
  183. return {}
  184. }
  185. // We get the index path to the folder itself,
  186. // we have to find the folder containing the target folder,
  187. // so we pop the last path index
  188. const folderIndex = indexPaths.pop() as number
  189. const containingFolder = navigateToFolderWithIndexPath(newState, indexPaths)
  190. if (containingFolder === null) {
  191. console.log(
  192. `Could not resolve path '${path}'. Skipping removeFolder dispatch.`
  193. )
  194. return {}
  195. }
  196. containingFolder.folders.splice(folderIndex, 1)
  197. return {
  198. state: newState,
  199. }
  200. },
  201. editRequest(
  202. { state }: RESTCollectionStoreType,
  203. {
  204. path,
  205. requestIndex,
  206. requestNew,
  207. }: { path: string; requestIndex: number; requestNew: any }
  208. ) {
  209. const newState = state
  210. const indexPaths = path.split("/").map((x) => parseInt(x))
  211. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  212. if (targetLocation === null) {
  213. console.log(
  214. `Could not resolve path '${path}'. Ignoring editRequest dispatch.`
  215. )
  216. return {}
  217. }
  218. targetLocation.requests = targetLocation.requests.map((req, index) =>
  219. index !== requestIndex ? req : requestNew
  220. )
  221. return {
  222. state: newState,
  223. }
  224. },
  225. saveRequestAs(
  226. { state }: RESTCollectionStoreType,
  227. { path, request }: { path: string; request: any }
  228. ) {
  229. const newState = state
  230. const indexPaths = path.split("/").map((x) => parseInt(x))
  231. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  232. if (targetLocation === null) {
  233. console.log(
  234. `Could not resolve path '${path}'. Ignoring saveRequestAs dispatch.`
  235. )
  236. return {}
  237. }
  238. targetLocation.requests.push(request)
  239. return {
  240. state: newState,
  241. }
  242. },
  243. removeRequest(
  244. { state }: RESTCollectionStoreType,
  245. { path, requestIndex }: { path: string; requestIndex: number }
  246. ) {
  247. const newState = state
  248. const indexPaths = path.split("/").map((x) => parseInt(x))
  249. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  250. if (targetLocation === null) {
  251. console.log(
  252. `Could not resolve path '${path}'. Ignoring removeRequest dispatch.`
  253. )
  254. return {}
  255. }
  256. targetLocation.requests.splice(requestIndex, 1)
  257. // If the save context is set and is set to the same source, we invalidate it
  258. const saveCtx = getRESTSaveContext()
  259. if (
  260. saveCtx?.originLocation === "user-collection" &&
  261. saveCtx.folderPath === path &&
  262. saveCtx.requestIndex === requestIndex
  263. ) {
  264. setRESTSaveContext(null)
  265. }
  266. return {
  267. state: newState,
  268. }
  269. },
  270. moveRequest(
  271. { state }: RESTCollectionStoreType,
  272. {
  273. path,
  274. requestIndex,
  275. destinationPath,
  276. }: { path: string; requestIndex: number; destinationPath: string }
  277. ) {
  278. const newState = state
  279. const indexPaths = path.split("/").map((x) => parseInt(x))
  280. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  281. if (targetLocation === null) {
  282. console.log(
  283. `Could not resolve source path '${path}'. Skipping moveRequest dispatch.`
  284. )
  285. return {}
  286. }
  287. const req = targetLocation.requests[requestIndex]
  288. const destIndexPaths = destinationPath.split("/").map((x) => parseInt(x))
  289. const destLocation = navigateToFolderWithIndexPath(newState, destIndexPaths)
  290. if (destLocation === null) {
  291. console.log(
  292. `Could not resolve destination path '${destinationPath}'. Skipping moveRequest dispatch.`
  293. )
  294. return {}
  295. }
  296. destLocation.requests.push(req)
  297. targetLocation.requests.splice(requestIndex, 1)
  298. return {
  299. state: newState,
  300. }
  301. },
  302. })
  303. const gqlCollectionDispatchers = defineDispatchers({
  304. setCollections(
  305. _: GraphqlCollectionStoreType,
  306. { entries }: { entries: Collection<any>[] }
  307. ) {
  308. return {
  309. state: entries,
  310. }
  311. },
  312. appendCollections(
  313. { state }: GraphqlCollectionStoreType,
  314. { entries }: { entries: Collection<any>[] }
  315. ) {
  316. return {
  317. state: [...state, ...entries],
  318. }
  319. },
  320. addCollection(
  321. { state }: GraphqlCollectionStoreType,
  322. { collection }: { collection: Collection<any> }
  323. ) {
  324. return {
  325. state: [...state, collection],
  326. }
  327. },
  328. removeCollection(
  329. { state }: GraphqlCollectionStoreType,
  330. { collectionIndex }: { collectionIndex: number }
  331. ) {
  332. return {
  333. state: (state as any).filter(
  334. (_: any, i: number) => i !== collectionIndex
  335. ),
  336. }
  337. },
  338. editCollection(
  339. { state }: GraphqlCollectionStoreType,
  340. {
  341. collectionIndex,
  342. collection,
  343. }: { collectionIndex: number; collection: Collection<any> }
  344. ) {
  345. return {
  346. state: state.map((col, index) =>
  347. index === collectionIndex ? collection : col
  348. ),
  349. }
  350. },
  351. addFolder(
  352. { state }: GraphqlCollectionStoreType,
  353. { name, path }: { name: string; path: string }
  354. ) {
  355. const newFolder: Collection<HoppGQLRequest> = makeCollection({
  356. name,
  357. folders: [],
  358. requests: [],
  359. })
  360. const newState = state
  361. const indexPaths = path.split("/").map((x) => parseInt(x))
  362. const target = navigateToFolderWithIndexPath(newState, indexPaths)
  363. if (target === null) {
  364. console.log(`Could not parse path '${path}'. Ignoring add folder request`)
  365. return {}
  366. }
  367. target.folders.push(newFolder)
  368. return {
  369. state: newState,
  370. }
  371. },
  372. editFolder(
  373. { state }: GraphqlCollectionStoreType,
  374. { path, folder }: { path: string; folder: string }
  375. ) {
  376. const newState = state
  377. const indexPaths = path.split("/").map((x) => parseInt(x))
  378. const target = navigateToFolderWithIndexPath(newState, indexPaths)
  379. if (target === null) {
  380. console.log(
  381. `Could not parse path '${path}'. Ignoring edit folder request`
  382. )
  383. return {}
  384. }
  385. Object.assign(target, folder)
  386. return {
  387. state: newState,
  388. }
  389. },
  390. removeFolder(
  391. { state }: GraphqlCollectionStoreType,
  392. { path }: { path: string }
  393. ) {
  394. const newState = state
  395. const indexPaths = path.split("/").map((x) => parseInt(x))
  396. if (indexPaths.length === 0) {
  397. console.log(
  398. "Given path too short. If this is a collection, use removeCollection dispatcher instead. Skipping request."
  399. )
  400. return {}
  401. }
  402. // We get the index path to the folder itself,
  403. // we have to find the folder containing the target folder,
  404. // so we pop the last path index
  405. const folderIndex = indexPaths.pop() as number
  406. const containingFolder = navigateToFolderWithIndexPath(newState, indexPaths)
  407. if (containingFolder === null) {
  408. console.log(
  409. `Could not resolve path '${path}'. Skipping removeFolder dispatch.`
  410. )
  411. return {}
  412. }
  413. containingFolder.folders.splice(folderIndex, 1)
  414. return {
  415. state: newState,
  416. }
  417. },
  418. editRequest(
  419. { state }: GraphqlCollectionStoreType,
  420. {
  421. path,
  422. requestIndex,
  423. requestNew,
  424. }: { path: string; requestIndex: number; requestNew: any }
  425. ) {
  426. const newState = state
  427. const indexPaths = path.split("/").map((x) => parseInt(x))
  428. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  429. if (targetLocation === null) {
  430. console.log(
  431. `Could not resolve path '${path}'. Ignoring editRequest dispatch.`
  432. )
  433. return {}
  434. }
  435. targetLocation.requests = targetLocation.requests.map((req, index) =>
  436. index !== requestIndex ? req : requestNew
  437. )
  438. return {
  439. state: newState,
  440. }
  441. },
  442. saveRequestAs(
  443. { state }: GraphqlCollectionStoreType,
  444. { path, request }: { path: string; request: any }
  445. ) {
  446. const newState = state
  447. const indexPaths = path.split("/").map((x) => parseInt(x))
  448. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  449. if (targetLocation === null) {
  450. console.log(
  451. `Could not resolve path '${path}'. Ignoring saveRequestAs dispatch.`
  452. )
  453. return {}
  454. }
  455. targetLocation.requests.push(request)
  456. return {
  457. state: newState,
  458. }
  459. },
  460. removeRequest(
  461. { state }: GraphqlCollectionStoreType,
  462. { path, requestIndex }: { path: string; requestIndex: number }
  463. ) {
  464. const newState = state
  465. const indexPaths = path.split("/").map((x) => parseInt(x))
  466. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  467. if (targetLocation === null) {
  468. console.log(
  469. `Could not resolve path '${path}'. Ignoring removeRequest dispatch.`
  470. )
  471. return {}
  472. }
  473. targetLocation.requests.splice(requestIndex, 1)
  474. // If the save context is set and is set to the same source, we invalidate it
  475. const saveCtx = getRESTSaveContext()
  476. if (
  477. saveCtx?.originLocation === "user-collection" &&
  478. saveCtx.folderPath === path &&
  479. saveCtx.requestIndex === requestIndex
  480. ) {
  481. setRESTSaveContext(null)
  482. }
  483. return {
  484. state: newState,
  485. }
  486. },
  487. moveRequest(
  488. { state }: GraphqlCollectionStoreType,
  489. {
  490. path,
  491. requestIndex,
  492. destinationPath,
  493. }: { path: string; requestIndex: number; destinationPath: string }
  494. ) {
  495. const newState = state
  496. const indexPaths = path.split("/").map((x) => parseInt(x))
  497. const targetLocation = navigateToFolderWithIndexPath(newState, indexPaths)
  498. if (targetLocation === null) {
  499. console.log(
  500. `Could not resolve source path '${path}'. Skipping moveRequest dispatch.`
  501. )
  502. return {}
  503. }
  504. const req = targetLocation.requests[requestIndex]
  505. const destIndexPaths = destinationPath.split("/").map((x) => parseInt(x))
  506. const destLocation = navigateToFolderWithIndexPath(newState, destIndexPaths)
  507. if (destLocation === null) {
  508. console.log(
  509. `Could not resolve destination path '${destinationPath}'. Skipping moveRequest dispatch.`
  510. )
  511. return {}
  512. }
  513. destLocation.requests.push(req)
  514. targetLocation.requests.splice(requestIndex, 1)
  515. return {
  516. state: newState,
  517. }
  518. },
  519. })
  520. export const restCollectionStore = new DispatchingStore(
  521. defaultRESTCollectionState,
  522. restCollectionDispatchers
  523. )
  524. export const graphqlCollectionStore = new DispatchingStore(
  525. defaultGraphqlCollectionState,
  526. gqlCollectionDispatchers
  527. )
  528. export function setRESTCollections(entries: Collection<HoppRESTRequest>[]) {
  529. restCollectionStore.dispatch({
  530. dispatcher: "setCollections",
  531. payload: {
  532. entries,
  533. },
  534. })
  535. }
  536. export const restCollections$ = restCollectionStore.subject$.pipe(
  537. pluck("state")
  538. )
  539. export const graphqlCollections$ = graphqlCollectionStore.subject$.pipe(
  540. pluck("state")
  541. )
  542. export function appendRESTCollections(entries: Collection<HoppRESTRequest>[]) {
  543. restCollectionStore.dispatch({
  544. dispatcher: "appendCollections",
  545. payload: {
  546. entries,
  547. },
  548. })
  549. }
  550. export function addRESTCollection(collection: Collection<HoppRESTRequest>) {
  551. restCollectionStore.dispatch({
  552. dispatcher: "addCollection",
  553. payload: {
  554. collection,
  555. },
  556. })
  557. }
  558. export function removeRESTCollection(collectionIndex: number) {
  559. restCollectionStore.dispatch({
  560. dispatcher: "removeCollection",
  561. payload: {
  562. collectionIndex,
  563. },
  564. })
  565. }
  566. export function editRESTCollection(
  567. collectionIndex: number,
  568. collection: Collection<HoppRESTRequest>
  569. ) {
  570. restCollectionStore.dispatch({
  571. dispatcher: "editCollection",
  572. payload: {
  573. collectionIndex,
  574. collection,
  575. },
  576. })
  577. }
  578. export function addRESTFolder(name: string, path: string) {
  579. restCollectionStore.dispatch({
  580. dispatcher: "addFolder",
  581. payload: {
  582. name,
  583. path,
  584. },
  585. })
  586. }
  587. export function editRESTFolder(
  588. path: string,
  589. folder: Collection<HoppRESTRequest>
  590. ) {
  591. restCollectionStore.dispatch({
  592. dispatcher: "editFolder",
  593. payload: {
  594. path,
  595. folder,
  596. },
  597. })
  598. }
  599. export function removeRESTFolder(path: string) {
  600. restCollectionStore.dispatch({
  601. dispatcher: "removeFolder",
  602. payload: {
  603. path,
  604. },
  605. })
  606. }
  607. export function editRESTRequest(
  608. path: string,
  609. requestIndex: number,
  610. requestNew: HoppRESTRequest
  611. ) {
  612. restCollectionStore.dispatch({
  613. dispatcher: "editRequest",
  614. payload: {
  615. path,
  616. requestIndex,
  617. requestNew,
  618. },
  619. })
  620. }
  621. export function saveRESTRequestAs(path: string, request: HoppRESTRequest) {
  622. // For calculating the insertion request index
  623. const targetLocation = navigateToFolderWithIndexPath(
  624. restCollectionStore.value.state,
  625. path.split("/").map((x) => parseInt(x))
  626. )
  627. const insertionIndex = targetLocation!.requests.length
  628. restCollectionStore.dispatch({
  629. dispatcher: "saveRequestAs",
  630. payload: {
  631. path,
  632. request,
  633. },
  634. })
  635. return insertionIndex
  636. }
  637. export function removeRESTRequest(path: string, requestIndex: number) {
  638. restCollectionStore.dispatch({
  639. dispatcher: "removeRequest",
  640. payload: {
  641. path,
  642. requestIndex,
  643. },
  644. })
  645. }
  646. export function moveRESTRequest(
  647. path: string,
  648. requestIndex: number,
  649. destinationPath: string
  650. ) {
  651. restCollectionStore.dispatch({
  652. dispatcher: "moveRequest",
  653. payload: {
  654. path,
  655. requestIndex,
  656. destinationPath,
  657. },
  658. })
  659. }
  660. export function setGraphqlCollections(entries: Collection<HoppGQLRequest>[]) {
  661. graphqlCollectionStore.dispatch({
  662. dispatcher: "setCollections",
  663. payload: {
  664. entries,
  665. },
  666. })
  667. }
  668. export function appendGraphqlCollections(
  669. entries: Collection<HoppGQLRequest>[]
  670. ) {
  671. graphqlCollectionStore.dispatch({
  672. dispatcher: "appendCollections",
  673. payload: {
  674. entries,
  675. },
  676. })
  677. }
  678. export function addGraphqlCollection(collection: Collection<HoppGQLRequest>) {
  679. graphqlCollectionStore.dispatch({
  680. dispatcher: "addCollection",
  681. payload: {
  682. collection,
  683. },
  684. })
  685. }
  686. export function removeGraphqlCollection(collectionIndex: number) {
  687. graphqlCollectionStore.dispatch({
  688. dispatcher: "removeCollection",
  689. payload: {
  690. collectionIndex,
  691. },
  692. })
  693. }
  694. export function editGraphqlCollection(
  695. collectionIndex: number,
  696. collection: Collection<HoppGQLRequest>
  697. ) {
  698. graphqlCollectionStore.dispatch({
  699. dispatcher: "editCollection",
  700. payload: {
  701. collectionIndex,
  702. collection,
  703. },
  704. })
  705. }
  706. export function addGraphqlFolder(name: string, path: string) {
  707. graphqlCollectionStore.dispatch({
  708. dispatcher: "addFolder",
  709. payload: {
  710. name,
  711. path,
  712. },
  713. })
  714. }
  715. export function editGraphqlFolder(
  716. path: string,
  717. folder: Collection<HoppGQLRequest>
  718. ) {
  719. graphqlCollectionStore.dispatch({
  720. dispatcher: "editFolder",
  721. payload: {
  722. path,
  723. folder,
  724. },
  725. })
  726. }
  727. export function removeGraphqlFolder(path: string) {
  728. graphqlCollectionStore.dispatch({
  729. dispatcher: "removeFolder",
  730. payload: {
  731. path,
  732. },
  733. })
  734. }
  735. export function editGraphqlRequest(
  736. path: string,
  737. requestIndex: number,
  738. requestNew: HoppGQLRequest
  739. ) {
  740. graphqlCollectionStore.dispatch({
  741. dispatcher: "editRequest",
  742. payload: {
  743. path,
  744. requestIndex,
  745. requestNew,
  746. },
  747. })
  748. }
  749. export function saveGraphqlRequestAs(path: string, request: HoppGQLRequest) {
  750. graphqlCollectionStore.dispatch({
  751. dispatcher: "saveRequestAs",
  752. payload: {
  753. path,
  754. request,
  755. },
  756. })
  757. }
  758. export function removeGraphqlRequest(path: string, requestIndex: number) {
  759. graphqlCollectionStore.dispatch({
  760. dispatcher: "removeRequest",
  761. payload: {
  762. path,
  763. requestIndex,
  764. },
  765. })
  766. }
  767. export function moveGraphqlRequest(
  768. path: string,
  769. requestIndex: number,
  770. destinationPath: string
  771. ) {
  772. graphqlCollectionStore.dispatch({
  773. dispatcher: "moveRequest",
  774. payload: {
  775. path,
  776. requestIndex,
  777. destinationPath,
  778. },
  779. })
  780. }