thunderclient / thunder-client-support

Thunder Client is a lightweight Rest API Client Extension for VS Code.
https://www.thunderclient.com
Other
3.59k stars 127 forks source link

Add env customization to each Collection #1014

Closed hyoretsu closed 1 month ago

hyoretsu commented 1 year ago

Currently, all variable from Env need to be shared. This isn't ideal when you wanna test in production, where each collection (project) has its own URL.

rangav commented 1 year ago

Hi @hyoretsu , You can use baseUrl in Collection settings for URL

Screenshot 2023-02-10 at 20 46 10
hyoretsu commented 1 year ago

Yes, that's what I'm doing. I created a dev environment and am sharing that URL through all my collections image But I want to test in prod environment, where each collection has a different URL.

rangav commented 1 year ago

Then you can use multiple variables

Example

hyoretsu commented 1 year ago

That's a workaround. They all have the same value in dev env and symbolize the same thing in prod. If I have 50 collections, I'd need 50 variables, even for dev

rangav commented 1 year ago

What is your suggestion?

hyoretsu commented 1 year ago

Make the current variables global, and let us define collection variables.

E.g. I have two envs, dev and prod, with a host variable. dev value is localhost:3333 and prod value is a shared domain used to test APIs. But then I work on a project and deploy it to its own domain. I then go to that Collection settings and override the host variable for prod env to its own URL. (Sort of like a .env, but using only the extension)

rangav commented 1 year ago

Make the current variables global

Did not understood the above? We already have local and global environments which are global.

if we have collection variables also

hyoretsu commented 1 year ago

if we have collection variables also

  • You still have to create 50 variables right?

Only if all your collections have different values. If not, you can share the same one.

  • How do you have different variable values of different environments like dev and prod

All my dev host URLs are localhost:3333. (The same way I can buy a domain and deploy all my APIs there) But I can't test a collection in prod with its own URL because I can only set global variables.

rangav commented 1 year ago

Its still not clear to me,

If its same value in dev - how will you set the value?

and how will you change to different host url in prod?

hyoretsu commented 1 year ago

and how will you change to different host url in prod?

That's what currently isn't possible, changing values per env in a per-collection basis.

If its same value in dev - how will you set the value?

By using the current implementation to set a global variable.

Basically a env collection overriding.

rangav commented 1 year ago

Then you can use multiple variables

Example

  • for ColA - set baseurl to {{hostA}}
  • for ColB - set baseurl to {{hostB}}
  • for ColC - set baseurl to {{hostC}}

The above will work for your situation, this is how most users are using it currently. Please try this.

As your suggestions also will not solve completely

hyoretsu commented 1 year ago

Then I need to have hostA set to localhost:3333 in dev and mytestsite.com/api in prod hostB set to localhost:3333 in dev and mytestsite.com/api in prod hostC set to localhost:3333 in dev and mytestsite.com/api in prod hostD set to localhost:3333 in dev and mytestsite.com/api in prod hostE set to localhost:3333 in dev and mytestsite.com/api in prod hostF set to localhost:3333 in dev and mytestsite.com/api in prod hostG set to localhost:3333 in dev and sti.ufpb.br/api in prod

See where I'm getting at? Lots of redundancy in the current workaround. What I'm suggesting is:

host set to localhost:3333 in dev and mytestsite.com/api in prod and overriding it for sti.ufpb.br/api in prod only in project G.

If it doesn't solve completely, it's way better.

rangav commented 1 year ago

host set to localhost:3333 in dev and mytestsite.com/api in prod and overriding it for sti.ufpb.br/api in prod only in project G.

I didn’t understand how we can achieve this? Its not possible by having collection variables right?

as collection variables will not change based on environment right?

just clarification - where you want this collection variables location in UI?

rangav commented 1 year ago

How many collections you? I know there is redundancy, but it gives more flexibility also incase you want different urls in prod

hyoretsu commented 1 year ago

I know there is redundancy, but it gives more flexibility also incase you want different urls in prod

Flexibility that would be present just the same with collection overriding.

I didn’t understand how we can achieve this? Its not possible by having collection variables right?

Basically, in simple coding:

const globalVariables = {
 dev: {
  host: 'localhost:3333'
 },
 prod: {
  host: 'mytestsite.com/api'
 },
};

const projectGVariables = {
 prod: {
  host: 'sti.ufpb.br/api'
 }
};

const actualVariablesG = {
 ...globalVariables,
 ...projectGVariables,
};

Except that this implementation replaces all variables, not only the ones that were overriden.

as collection variables will not change based on environment right?

They will.

where you want this collection variables location in UI?

Each collection, in Settings, will have an Env tab with a list of the envs defined in the current Env section. There, you'd be able to define project-specific variables (env-dependant), that'd either be added or overwritten.

rangav commented 1 year ago

That looks very complicated, its look very specific use-case related solution. And they have to enter all that text manually without UI.

I understood your problem, but don’t think it is good solution.

hyoretsu commented 1 year ago

That looks very complicated, its look very specific use-case related solution. And they have to enter all that text manually without UI.

No, they wouldn't. I explained where it'd be in the UI.

Each collection, in Settings, will have an Env tab with a list of the envs defined in the current Env section. There, you'd be able to define project-specific variables (env-dependant), that'd either be added or overwritten.

I understood your problem, but don’t think it is good solution.

It's what Imsomnia, a famous app, does. It has a base environment and sub-environments (dev, prod). Base is always available, and Subs are merged with Base. The only difference is that their envs are all collection-specific. It isn't specific at all, just a common problem.

rangav commented 1 year ago

Our environments works differently from insomnia.

so we cannot change our environments to make it work like insomnia for just one use-case.

Ours is UI based environments, where in insomnia you have to manually type json.

hyoretsu commented 1 year ago

Is it normal for dev servers to all have the same URL/port? Yes. Is it normal to deploy (some) APIs to a URL of their own? Yes. Is it normal to cheap out on hobby projects and have a single domain to test and then deploy to its own domain? (having a default host for prod) I don't know, maybe.

Don't see how it's uncommon, or how it'd be (very) hard with Thunder Client's UI-based envs. It should either be an array or a JSON/form, both of which you can merge.

rangav commented 1 year ago

Unfortunately cannot implement this suggestion.

rangav commented 1 year ago

Then you can use multiple variables

Example

  • for ColA - set baseurl to {{hostA}}
  • for ColB - set baseurl to {{hostB}}
  • for ColC - set baseurl to {{hostC}}

Currently we recommend this approach.

bretonics commented 1 year ago

I think this is a similar thing I was just looking to do, but please let me know otherwise @hyoretsu, or if I should create a feature request @rangav.

I want to have Collection Variables.

Why? Because I want to specify a baseUrl variable in an Environments config that I can reference as suggested in Collections by @rangav, i.e: setting "Base URLs" in the collection settings to {{baseUrl}}.

So say I have 3 Environments,dev, test, prod, but their base URLs differ slightly:

Setting "Base URLs" in the collection settings to {{baseUrl}} works as suggested.

Now assuming most users use "Collections" as a collection of request for the same "app", which differs between each "Collection"/app, then each request in each Collection needs to have the same {{app}} variable inserted in the "BaseURL".

So having Collection variables adds this additional flexibility and feature! This also means that dev, which is a completely different URL, can still be used!

Having a Collection variable will allow us to have 1 Collection of requests that can be used for all environments. This also avoids having 3 Environments for each Collection, or 3 Collection for each Environment.

rangav commented 1 year ago

Hi @bretonics, Thanks for the feedback.

For baseUrl you can use Collection Settings -> BaseUrl options

Screenshot 2023-02-27 at 20 56 06
bretonics commented 1 year ago

@rangav, exactly, and that's what I am doing. But, dependent on which of the 3 Environments is active; dev, test, or prod, their base URLs differ slightly:

dev: baseUrl={{protocol}}://localhost:{{port}} test: baseUrl={{protocol}}://{{app}}-test.{{domain}} prod: baseUrl={{protocol}}://{{app}}.{{domain}}

However, I can't define {{app}} anywhere to make it dynamically. The variable app is technically part of the Colllection, and differs between each Collection, i.e. each app. Say I have 2 Collections, one for "App1" and another for "App2".

If I defined the Collection Settings -> BaseUrl options for each Collection as mentioned, the {{baseUrl}} ends up being the same for both Collections, in all Environments, unless I can define a dynamic variable, like {{app}} in each Collection.

Hope that helps clarify a bit more.

Thank you!

rangav commented 1 year ago

Thanks @bretonics its clear now.

I think you can use as below test: baseUrl={{protocol}}://{{appTest}}-test.{{domain}} prod: baseUrl={{protocol}}://{{appProd}}.{{domain}}

bretonics commented 1 year ago

@rangav , right...but were do I defined the {{appTest}} and {{appProd}} values?

This means I would need 2 Collections, 1 for each Environment, for the same Collection of requests: e.g. "Collection App 1 Dev" and "Collection App 1 Test". I would have to do the same thing for "Collection 2". That's 4 Collections instead of 2 (each a duplicate of the other Collection's corresponding Environment).

If we had "Collection Variables" I could apply the same Environment variable, baseUrl={{protocol}}://{{app}}-test.{{domain}}, to all collections.

Here's a similar scenario...let's forget Environment variables.

Say I define baseUrl=https://{{app}}.myCoolDomain.com as a Global variable and I have 3 Collections, 1 for each different app (ShoppingApp, MarketingApp, MemeApp).

I need each Collection's "app name" (shopping, marketing, meme) to be interpolated into the {{app}} variable. Thus, I would need a "Collection variable" specific and different for each Collection/App in order for the request to hit the correct route in it's corresponding Collection, i.e.:

rangav commented 1 year ago

You dont need 4 collections.

You can define the {{appTest}} and {{appProd}} variables and both test and prod environments. Depending on which env is active, the collection will get the corresponding values.

hyoretsu commented 1 year ago

@bretonics it's not possible to have dynamic variables currently, and it isn't in the plans because (theoretically) it isn't possible.

bretonics commented 1 year ago

Can Collection variables be an added feature? This will solve a common use case

hyoretsu commented 1 year ago

That looks very complicated, its look very specific use-case related solution.

Our environments works differently from insomnia.

so we cannot change our environments to make it work like insomnia for just one use-case.

Ours is UI based environments, where in insomnia you have to manually type json.

(don't see how getting data from a JSON is much harder than getting it through an UI, especially if it's a form, but sure)

Unfortunately cannot implement this suggestion.

While it also isn't open-source so someone can make a PR for it.

rangav commented 1 year ago

@bretonics @hyoretsu

if you still prefer collection specific variables, there is a workaround

you can define collection specific variables in a separate env and attach to a collection in the collection settings-> environment tab

you can try and let me know if that’s useful

bretonics commented 1 year ago

@rangav , thanks but kind of works for this use case. It does provide a way to add more variables, but not distinct per Collection, rather this solution adds distinct variables to Environments. I need distinct variables per Collection.

To do so and use the approach suggested with the .env file, I'd need to attach a Collection to a specific Environment with the specific .env file. That's why that's not reusable nor extensible...I won't be able to reuse the same Environment for all Collection because. the {{app}} variable defined in the .env file in the Environment will be the same for all Collections (shopping, marketing, meme).

So again, say I need 3 Collections for 3 different applications, each with it's similar, yet unique URL. Each Collection's "app name" (shopping, marketing, meme) needs to be interpolated into the {{app}} variable of the baseUrl defined in the Environment, which is then set in the Collection's "Base Url" setting as {{baseUrl}}. Thus, I would need a "Collection variable" specific and different for each Collection/App in order for the request to hit the correct route in it's corresponding Collection, i.e.:

Consider the configurations...

thunderEnvironment.json

[
  {
    "name": "Global Env",
    "default": false,
    "global": true,
    "data": [
      {
        "name": "protocol",
        "value": "https"
      },
      {
        "name": "domain",
        "value": "myCoolDomain.com"
      }
    ]
  },
  {
    "name": "Dev",
    "default": false,
    "data": [
      {
        "name": "protocol",
        "value": "http"
      },
      {
        "name": "port",
        "value": "4200"
      },
      {
        "name": "baseUrl",
        "value": "{{protocol}}://localhost:port"
      }
    ]
  },
  {
    "name": "Test",
    "default": true,
    "data": [
      {
        "name": "baseUrl",
        "value": "{{protocol}}://{{app}}-test.{{domain}}"
      }
    ]
  },
  {
    "name": "Prod",
    "default": false,
    "data": [
      {
        "name": "baseUrl",
        "value": "{{protocol}}://{{app}}.{{domain}}"
      }
    ]
  },
]

thunderCollection.json

[
  {
    "colName": "Shopping",
    "folders": [],
    "settings": {
      "options": {
        "baseUrl": "{{baseUrl}}"
      }
    }
  },
  {
    "colName": "Marketing",
    "folders": [],
    "settings": {
      "options": {
        "baseUrl": "{{baseUrl}}"
      }
    }
  },
  {
    "colName": "Meme",
    "folders": [],
    "settings": {
      "options": {
        "baseUrl": "{{baseUrl}}"
      }
    }
  }
]

With the above configurations, let me select any Collection...say the "Shopping" one as an example...and the "Test" Environment set as active. I can't use the {{app}} variable used in the defined {{baseUrl}}of the Environment (which is later used in the Collection's base url setting) because I can't define it anywhere in the Collection.

If I defined {{app}} in the .env of an Environment, that will interpolate it into the Collection's {{baseUrl}} as expected, but that means it's hard coded to that Environment and I can't reuse this Environment with another Collection. Why? Consider the .env for this:

app=shopping

If I attached this to the "Test" Environment and have this Environment active, when I make a request in the "Shopping" Collection...excellent, it works as expected.

Now, let's use another Collection...say "Marketing"...and I still have the "Test" Environment active (because I need to hit the test site's URL), the request won't be made to https://marketing.myCoolDomain.com but instead to https://shopping.myCoolDomain.com because that's what is defined in the .env for that Environment. Same if I were to set the {{app}} variable in the Environment settings directly.

This is distinct to having Collection specific variables, which would solve this common use case.

How? By allowing distinct variables that add to the current "Global" and "Environment" variables.

In the scenario above with the configurations mentioned, you would only need to simply add an app variable in each Collection, i.e. app=shopping, app=marketing, app=meme, corresponding to the appropriate Collection and thus the {{baseUrl}}(defined in the current active Environment, {{protocol}}://{{app}}-test.{{domain}} for the "Test" Environment) will be interpolated into the Collection's "Base Url" settings correctly:

Then changing to another Environment, like "Prod", will also interpolate the right {{baseUrl}} for each Collection/App:

That minimal additional adds a lot of flexibility.

Hope this is much more clear.

rangav commented 1 year ago

Hi @bretonics create a new environment for collection specific variables and attach to collection. This environment will be specific to this collection

image

bretonics commented 1 year ago

Hi @bretonics create a new environment for collection specific variables and attach to collection. This environment will be specific to this collection

Sure, that works, but only if the URL schema's are very similar but not if the baseUrl differ drastically, such as dev environments as the Collection's attached Environment overrides the active Environment:

Test and prod work, but the dev environment's baseUrl definition is overwritten by the "new environment for collection specific variables attached to the collection". In other words, an active dev environment is useless.

I am not sure if I am not getting my point across and can't showcase the difference for a common use case that is not addressed by all the suggested solutions, but don't know how else to exemplify how this doesn't work and Collection specific variables are essential.

Thanks for the suggestions anyways.

rangav commented 1 year ago

I will test with your sample data and get back to you.