diff --git a/CHANGELOG.md b/CHANGELOG.md index 438a0511a..3b1009f32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,12 @@ +## v2.0.0-beta +FEATURES: +- Support `workspace/executeCommand` protocol which can convert ARMTemplate and resource JSON content to azapi configuration. +- `azapi_resource` resource: Support `replace_triggers_external_values` field which is used to trigger a replacement of the resource. +- `azapi` resources and data sources: Support `retry` field, which is used to specify the retry configuration. +- `azapi` resources and data sources: Support `headers` and `query_parameters` fields, which are used to specify the headers and query parameters. +- `azapi` resources and data sources: The `response_export_values` field supports JMESPath expressions. + + ## v1.15.0 ENHANCEMENTS: - Update bicep types to https://github.com/ms-henglu/bicep-types-az/commit/5ccee7fe1b353e40ed86bfc530ee185faa43a288 diff --git a/internal/langserver/handlers/testdata/TestCompletion_codeSample/expect.json b/internal/langserver/handlers/testdata/TestCompletion_codeSample/expect.json index 5f285795c..52e05ef86 100644 --- a/internal/langserver/handlers/testdata/TestCompletion_codeSample/expect.json +++ b/internal/langserver/handlers/testdata/TestCompletion_codeSample/expect.json @@ -187,7 +187,7 @@ "detail": "body (Optional)", "documentation": { "kind": "markdown", - "value": "Type: `string ` \nA JSON object that contains the request body used to create and update azure resource.\n" + "value": "Type: `dynamic` \nAn HCL object that contains the request body used to create and update azure resource.\n" }, "sortText": "0005", "insertTextFormat": 2, @@ -247,7 +247,7 @@ "detail": "response_export_values (Optional)", "documentation": { "kind": "markdown", - "value": "Type: `list` \nA list of path that needs to be exported from response body.\n" + "value": "Type: `list or map` \nThe attribute can accept either a list or a map of path that needs to be exported from response body.\n" }, "sortText": "0007", "insertTextFormat": 2, @@ -271,13 +271,13 @@ } }, { - "label": "schema_validation_enabled", + "label": "replace_triggers_external_values", "labelDetails": {}, "kind": 10, - "detail": "schema_validation_enabled (Optional)", + "detail": "replace_triggers_external_values (Optional)", "documentation": { "kind": "markdown", - "value": "Type: `bool` \nWhether enabled the validation on `type` and `body` with embedded schema. Defaults to `true`.\n" + "value": "Type: `dynamic` \nWill trigger a replace of the resource when the value changes and is not `null`.\n" }, "sortText": "0008", "insertTextFormat": 2, @@ -293,7 +293,7 @@ "character": 2 } }, - "newText": "schema_validation_enabled = $0" + "newText": "replace_triggers_external_values = $0" }, "command": { "title": "Suggest", @@ -301,13 +301,13 @@ } }, { - "label": "locks", + "label": "retry", "labelDetails": {}, "kind": 10, - "detail": "locks (Optional)", + "detail": "retry (Optional)", "documentation": { "kind": "markdown", - "value": "Type: `list` \nA list of ARM resource IDs which are used to avoid create/modify/delete azapi resources at the same time.\n" + "value": "Type: `block` \nConfiguration block for custom retry policy.\n" }, "sortText": "0009", "insertTextFormat": 2, @@ -323,7 +323,7 @@ "character": 2 } }, - "newText": "locks = [$0]" + "newText": "retry {\n\tinterval_seconds = $1\n\tmax_interval_seconds = $2\n\tmultiplier = $3\n\trandomization_factor = $4\n}" }, "command": { "title": "Suggest", @@ -331,13 +331,13 @@ } }, { - "label": "ignore_body_changes", + "label": "schema_validation_enabled", "labelDetails": {}, "kind": 10, - "detail": "ignore_body_changes (Optional)", + "detail": "schema_validation_enabled (Optional)", "documentation": { "kind": "markdown", - "value": "Type: `list` \nA list of properties that should be ignored when comparing the `body` with its current state..\n" + "value": "Type: `bool` \nWhether enabled the validation on `type` and `body` with embedded schema. Defaults to `true`.\n" }, "sortText": "0010", "insertTextFormat": 2, @@ -353,7 +353,37 @@ "character": 2 } }, - "newText": "ignore_body_changes = [$0]" + "newText": "schema_validation_enabled = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "locks", + "labelDetails": {}, + "kind": 10, + "detail": "locks (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `list` \nA list of ARM resource IDs which are used to avoid create/modify/delete azapi resources at the same time.\n" + }, + "sortText": "0011", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "locks = [$0]" }, "command": { "title": "Suggest", @@ -369,7 +399,7 @@ "kind": "markdown", "value": "Type: `bool` \nWhether ignore incorrect casing returned in `body` to suppress plan-diff. Defaults to `false`.\n" }, - "sortText": "0011", + "sortText": "0012", "insertTextFormat": 2, "insertTextMode": 2, "textEdit": { @@ -399,7 +429,7 @@ "kind": "markdown", "value": "Type: `bool` \nWhether ignore not returned properties like credentials in `body` to suppress plan-diff. Defaults to `false`.\n" }, - "sortText": "0012", + "sortText": "0013", "insertTextFormat": 2, "insertTextMode": 2, "textEdit": { @@ -419,6 +449,246 @@ "title": "Suggest", "command": "editor.action.triggerSuggest" } + }, + { + "label": "create_headers", + "labelDetails": {}, + "kind": 10, + "detail": "create_headers (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map` \nA mapping of headers which should be sent with the create request.\n" + }, + "sortText": "0014", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "create_headers = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "update_headers", + "labelDetails": {}, + "kind": 10, + "detail": "update_headers (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map` \nA mapping of headers which should be sent with the update request.\n" + }, + "sortText": "0015", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "update_headers = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "read_headers", + "labelDetails": {}, + "kind": 10, + "detail": "read_headers (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map` \nA mapping of headers which should be sent with the read request.\n" + }, + "sortText": "0016", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "read_headers = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "delete_headers", + "labelDetails": {}, + "kind": 10, + "detail": "delete_headers (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map` \nA mapping of headers which should be sent with the delete request.\n" + }, + "sortText": "0017", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "delete_headers = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "create_query_parameters", + "labelDetails": {}, + "kind": 10, + "detail": "create_query_parameters (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map>` \nA mapping of query parameters which should be sent with the create request.\n" + }, + "sortText": "0018", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "create_query_parameters = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "update_query_parameters", + "labelDetails": {}, + "kind": 10, + "detail": "update_query_parameters (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map>` \nA mapping of query parameters which should be sent with the update request.\n" + }, + "sortText": "0019", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "update_query_parameters = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "read_query_parameters", + "labelDetails": {}, + "kind": 10, + "detail": "read_query_parameters (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map>` \nA mapping of query parameters which should be sent with the read request.\n" + }, + "sortText": "0020", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "read_query_parameters = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } + }, + { + "label": "delete_query_parameters", + "labelDetails": {}, + "kind": 10, + "detail": "delete_query_parameters (Optional)", + "documentation": { + "kind": "markdown", + "value": "Type: `map>` \nA mapping of query parameters which should be sent with the delete request.\n" + }, + "sortText": "0021", + "insertTextFormat": 2, + "insertTextMode": 2, + "textEdit": { + "range": { + "start": { + "line": 2, + "character": 2 + }, + "end": { + "line": 2, + "character": 2 + } + }, + "newText": "delete_query_parameters = $0" + }, + "command": { + "title": "Suggest", + "command": "editor.action.triggerSuggest" + } } ] } diff --git a/internal/langserver/handlers/tfschema/init.go b/internal/langserver/handlers/tfschema/init.go index e67625d89..bf3b14439 100644 --- a/internal/langserver/handlers/tfschema/init.go +++ b/internal/langserver/handlers/tfschema/init.go @@ -5,6 +5,44 @@ import lsp "github.com/Azure/azapi-lsp/internal/protocol" func init() { Resources = make([]Resource, 0) + retryProperty := Property{ + Name: "retry", + Modifier: "Optional", + Type: "block", + Description: "Configuration block for custom retry policy.", + CompletionNewText: "retry {\n\tinterval_seconds = $1\n\tmax_interval_seconds = $2\n\tmultiplier = $3\n\trandomization_factor = $4\n}", + NestedProperties: []Property{ + { + Name: "interval_seconds", + Modifier: "Optional", + Type: "number", + Description: "The base number of seconds to wait between retries. Default is `10`.", + CompletionNewText: "interval_seconds = $0", + }, + { + Name: "max_interval_seconds", + Modifier: "Optional", + Type: "number", + Description: "The maximum number of seconds to wait between retries. Default is `180`.", + CompletionNewText: "max_interval_seconds = $0", + }, + { + Name: "multiplier", + Modifier: "Optional", + Type: "number", + Description: "The multiplier to apply to the interval between retries. Default is `1.5`.", + CompletionNewText: "multiplier = $0", + }, + { + Name: "randomization_factor", + Modifier: "Optional", + Type: "number", + Description: "The randomization factor to apply to the interval between retries. The formula for the randomized interval is: `RetryInterval * (random value in range [1 - RandomizationFactor, 1 + RandomizationFactor])`. Therefore set to zero `0.0` for no randomization. Default is `0.5`.", + CompletionNewText: "randomization_factor = $0", + }, + }, + } + Resources = append(Resources, Resource{ Name: "resource.azapi_resource", @@ -72,8 +110,8 @@ func init() { { Name: "body", Modifier: "Optional", - Type: "string ", - Description: "A JSON object that contains the request body used to create and update azure resource.", + Type: "dynamic", + Description: "An HCL object that contains the request body used to create and update azure resource.", CompletionNewText: `body = $0`, ValueCandidatesFunc: FixedValueCandidatesFunc([]lsp.CompletionItem{dynamicPlaceholderCandidate()}), GenericCandidatesFunc: bodyCandidates, @@ -90,11 +128,21 @@ func init() { { Name: "response_export_values", Modifier: "Optional", - Type: "list", - Description: "A list of path that needs to be exported from response body.", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", CompletionNewText: `response_export_values = [$0]`, }, + { + Name: "replace_triggers_external_values", + Modifier: "Optional", + Type: "dynamic", + Description: "Will trigger a replace of the resource when the value changes and is not `null`.", + CompletionNewText: `replace_triggers_external_values = $0`, + }, + + retryProperty, + { Name: "schema_validation_enabled", Modifier: "Optional", @@ -112,14 +160,6 @@ func init() { CompletionNewText: `locks = [$0]`, }, - { - Name: "ignore_body_changes", - Modifier: "Optional", - Type: "list", - Description: "A list of properties that should be ignored when comparing the `body` with its current state..", - CompletionNewText: `ignore_body_changes = [$0]`, - }, - { Name: "ignore_casing", Modifier: "Optional", @@ -137,6 +177,70 @@ func init() { CompletionNewText: `ignore_missing_property = $0`, ValueCandidatesFunc: boolCandidates, }, + + { + Name: "create_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the create request.", + CompletionNewText: `create_headers = $0`, + }, + + { + Name: "update_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the update request.", + CompletionNewText: `update_headers = $0`, + }, + + { + Name: "read_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the read request.", + CompletionNewText: `read_headers = $0`, + }, + + { + Name: "delete_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the delete request.", + CompletionNewText: `delete_headers = $0`, + }, + + { + Name: "create_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the create request.", + CompletionNewText: `create_query_parameters = $0`, + }, + + { + Name: "update_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the update request.", + CompletionNewText: `update_query_parameters = $0`, + }, + + { + Name: "read_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the read request.", + CompletionNewText: `read_query_parameters = $0`, + }, + + { + Name: "delete_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the delete request.", + CompletionNewText: `delete_query_parameters = $0`, + }, }, }, Resource{ @@ -178,8 +282,8 @@ func init() { { Name: "body", Modifier: "Optional", - Type: "string ", - Description: "A JSON object that contains the request body used to create and update azure resource.", + Type: "dynamic", + Description: "An HCL object that contains the request body used to create and update azure resource.", CompletionNewText: `body = $0`, ValueCandidatesFunc: FixedValueCandidatesFunc([]lsp.CompletionItem{dynamicPlaceholderCandidate()}), GenericCandidatesFunc: bodyCandidates, @@ -188,11 +292,118 @@ func init() { { Name: "response_export_values", Modifier: "Optional", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", + CompletionNewText: `response_export_values = [$0]`, + }, + + retryProperty, + + { + Name: "locks", + Modifier: "Optional", Type: "list", - Description: "A list of path that needs to be exported from response body.", + Description: "A list of ARM resource IDs which are used to avoid create/modify/delete azapi resources at the same time.", + CompletionNewText: `locks = [$0]`, + }, + + { + Name: "ignore_casing", + Modifier: "Optional", + Type: "bool", + Description: "Whether ignore incorrect casing returned in `body` to suppress plan-diff. Defaults to `false`.", + CompletionNewText: `ignore_casing = $0`, + ValueCandidatesFunc: boolCandidates, + }, + + { + Name: "ignore_missing_property", + Modifier: "Optional", + Type: "bool", + Description: "Whether ignore not returned properties like credentials in `body` to suppress plan-diff. Defaults to `false`.", + CompletionNewText: `ignore_missing_property = $0`, + ValueCandidatesFunc: boolCandidates, + }, + + { + Name: "update_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the update request.", + CompletionNewText: `update_headers = $0`, + }, + + { + Name: "read_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the read request.", + CompletionNewText: `read_headers = $0`, + }, + + { + Name: "update_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the update request.", + CompletionNewText: `update_query_parameters = $0`, + }, + + { + Name: "read_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the read request.", + CompletionNewText: `read_query_parameters = $0`, + }, + }, + }, + Resource{ + Name: "resource.azapi_data_plane_resource", + Properties: []Property{ + { + Name: "type", + Modifier: "Required", + Type: "string @", + Description: "Azure Resource Manager type.", + CompletionNewText: `type = "$0"`, + }, + + { + Name: "name", + Modifier: "Optional", + Type: "string", + Description: "Specifies the name of the azure resource. Changing this forces a new resource to be created.\n\nConfiguring `name` and `parent_id` is an alternative way to configure `resource_id`.", + CompletionNewText: `name = "$0"`, + }, + + { + Name: "parent_id", + Modifier: "Optional", + Type: "string", + Description: "The ID of the azure resource in which this resource is created. Changing this forces a new resource to be created.\n\nConfiguring `name` and `parent_id` is an alternative way to configure `resource_id`.", + CompletionNewText: `parent_id = $0`, + }, + + { + Name: "body", + Modifier: "Optional", + Type: "dynamic", + Description: "An HCL object that contains the request body used to create and update azure resource.", + CompletionNewText: `body = $0`, + ValueCandidatesFunc: FixedValueCandidatesFunc([]lsp.CompletionItem{dynamicPlaceholderCandidate()}), + }, + + { + Name: "response_export_values", + Modifier: "Optional", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", CompletionNewText: `response_export_values = [$0]`, }, + retryProperty, + { Name: "locks", Modifier: "Optional", @@ -218,6 +429,70 @@ func init() { CompletionNewText: `ignore_missing_property = $0`, ValueCandidatesFunc: boolCandidates, }, + + { + Name: "create_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the create request.", + CompletionNewText: `create_headers = $0`, + }, + + { + Name: "update_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the update request.", + CompletionNewText: `update_headers = $0`, + }, + + { + Name: "read_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the read request.", + CompletionNewText: `read_headers = $0`, + }, + + { + Name: "delete_headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the delete request.", + CompletionNewText: `delete_headers = $0`, + }, + + { + Name: "create_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the create request.", + CompletionNewText: `create_query_parameters = $0`, + }, + + { + Name: "update_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the update request.", + CompletionNewText: `update_query_parameters = $0`, + }, + + { + Name: "read_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the read request.", + CompletionNewText: `read_query_parameters = $0`, + }, + + { + Name: "delete_query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the delete request.", + CompletionNewText: `delete_query_parameters = $0`, + }, }, }, Resource{ @@ -259,10 +534,28 @@ func init() { { Name: "response_export_values", Modifier: "Optional", - Type: "list", - Description: "A list of path that needs to be exported from response body.", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", CompletionNewText: `response_export_values = [$0]`, }, + + retryProperty, + + { + Name: "headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the request.", + CompletionNewText: `headers = $0`, + }, + + { + Name: "query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the request.", + CompletionNewText: `query_parameters = $0`, + }, }, }, Resource{ @@ -306,8 +599,8 @@ func init() { { Name: "body", Modifier: "Optional", - Type: "string ", - Description: "A JSON object that contains the request body.", + Type: "dynamic", + Description: "An HCL object that contains the request body.", CompletionNewText: `body = $0`, ValueCandidatesFunc: FixedValueCandidatesFunc([]lsp.CompletionItem{dynamicPlaceholderCandidate()}), GenericCandidatesFunc: bodyCandidates, @@ -316,10 +609,28 @@ func init() { { Name: "response_export_values", Modifier: "Optional", - Type: "list", - Description: "A list of path that needs to be exported from response body.", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", CompletionNewText: `response_export_values = [$0]`, }, + + retryProperty, + + { + Name: "headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the request.", + CompletionNewText: `headers = $0`, + }, + + { + Name: "query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the request.", + CompletionNewText: `query_parameters = $0`, + }, }, }, Resource{ @@ -363,8 +674,8 @@ func init() { { Name: "body", Modifier: "Optional", - Type: "string ", - Description: "A JSON object that contains the request body.", + Type: "dynamic", + Description: "An HCL object that contains the request body.", CompletionNewText: `body = $0`, ValueCandidatesFunc: FixedValueCandidatesFunc([]lsp.CompletionItem{dynamicPlaceholderCandidate()}), GenericCandidatesFunc: bodyCandidates, @@ -373,10 +684,28 @@ func init() { { Name: "response_export_values", Modifier: "Optional", - Type: "list", - Description: "A list of path that needs to be exported from response body.", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", CompletionNewText: `response_export_values = [$0]`, }, + + retryProperty, + + { + Name: "headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the request.", + CompletionNewText: `headers = $0`, + }, + + { + Name: "query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the request.", + CompletionNewText: `query_parameters = $0`, + }, }, }, Resource{ @@ -402,10 +731,28 @@ func init() { { Name: "response_export_values", Modifier: "Optional", - Type: "list", - Description: "A list of path that needs to be exported from response body.", + Type: "list or map", + Description: "The attribute can accept either a list or a map of path that needs to be exported from response body.", CompletionNewText: `response_export_values = [$0]`, }, + + retryProperty, + + { + Name: "headers", + Modifier: "Optional", + Type: "map", + Description: "A mapping of headers which should be sent with the request.", + CompletionNewText: `headers = $0`, + }, + + { + Name: "query_parameters", + Modifier: "Optional", + Type: "map>", + Description: "A mapping of query parameters which should be sent with the request.", + CompletionNewText: `query_parameters = $0`, + }, }, }, Resource{