trmnl_preview 0.13.2 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +1 -0
- data/lib/trmnlp/config/plugin.rb +27 -5
- data/lib/trmnlp/lint/checks/custom_fields_used.rb +5 -3
- data/lib/trmnlp/lint/source.rb +9 -0
- data/lib/trmnlp/oauth/client.rb +2 -3
- data/lib/trmnlp/oauth/provider.rb +1 -0
- data/lib/trmnlp/transform_pipeline.rb +8 -0
- data/lib/trmnlp/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 23e1959e442066534a715efcc371a9c7d4cb41c7dda22727712b12b7b1eb90af
|
|
4
|
+
data.tar.gz: fbf07c5d835d4981b0380ce774fdfb74edab699c16772e187776ba58a1aee152
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8caa7eeef62cb562df06f7e0b3e1fcbf025cabe1f98fcda83fc365a0ee0fa9d8ce70fca9a3c16514a8ce3c320296c234e96e358d45cf3481e2b0451772e8866a
|
|
7
|
+
data.tar.gz: 01b1248e629516ab0c1857138807a27066f7b4e97be26024dd5e3365152d399e3e301fefcb864eb8e355546a5d5d6149f7c9851a345a3c8f09819099cd54c5bc
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
|
|
2
2
|
# Changelog
|
|
3
3
|
|
|
4
|
+
## 0.14.0
|
|
5
|
+
|
|
6
|
+
- `trmnlp serve` and `build` print what the transform writes to stdout and stderr (`console.log`, `print`, `puts`), one `transform stdout:` / `transform stderr:` line each, so a transform can be debugged without returning its logs in the data. (#128)
|
|
7
|
+
- The OAuth token exchange and refresh honor `oauth_token_request_auth_method` the way the hosted service does: HTTP Basic only for `header`, otherwise the client credentials go in the request body. trmnlp used HTTP Basic whenever a client secret was set, so a provider that wants the credentials in the body rejected the callback with `invalid_client: client_id is required`. A plugin that relied on HTTP Basic locally sets `oauth_token_request_auth_method: header`, which the hosted service already needs. (#121)
|
|
8
|
+
- `polling_headers` are parsed the way the hosted service parses them: one header per line, `Name: Value` as well as `Name=Value`, a JSON object, and values that contain `=`. Before, trmnlp split only on `&`, so headers saved one per line made the whole poll fail with "cannot include CR/LF" and the markup and transform got no polled data (no `IDX_0`/`IDX_1`). (#127)
|
|
9
|
+
- `trmnlp lint` no longer reports a custom field as unused when only the serverless transform (`src/transform.{py,rb,php,js}`) reads it. Plugins that move their data handling into the transform, reading fields from `input["trmnl"]["plugin_settings"]["custom_fields_values"]`, got one "is not used in form fields or markup" warning per field. The check now searches the transform as well, and its message names it. (#136)
|
|
10
|
+
|
|
4
11
|
## 0.13.2
|
|
5
12
|
|
|
6
13
|
- `google_photos_picker`, `json`, `modal_trigger` and `oauth_provider_select` are known form field types, so `trmnlp lint`, `build` and `serve` no longer warn "unknown field_type" for them. The hosted service renders all four. (#137)
|
data/README.md
CHANGED
|
@@ -334,6 +334,7 @@ oauth_scopes: "read:user user:email"
|
|
|
334
334
|
oauth_pkce_enabled: "true" # optional, default false
|
|
335
335
|
# oauth_scope_separator: " " # optional; some providers use ","
|
|
336
336
|
# oauth_refresh_url: https://... # optional; defaults to oauth_token_url
|
|
337
|
+
# oauth_token_request_auth_method: header # optional; "header" sends the client credentials as HTTP Basic, otherwise they go in the body
|
|
337
338
|
```
|
|
338
339
|
|
|
339
340
|
Your OAuth app credentials stay local and are never synced, so set them in your environment:
|
data/lib/trmnlp/config/plugin.rb
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'cgi'
|
|
4
|
+
require 'json'
|
|
4
5
|
require 'yaml'
|
|
5
6
|
|
|
6
7
|
require_relative '../errors'
|
|
@@ -113,13 +114,34 @@ module TRMNLP
|
|
|
113
114
|
project_config.with_custom_fields(value, extra_variables:)
|
|
114
115
|
end
|
|
115
116
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
# Mirrors the hosted service's Plugins::Helpers::Transformer#string_to_hash.
|
|
118
|
+
def string_to_hash(str)
|
|
119
|
+
return json_to_hash(str) if str.strip.start_with?('{')
|
|
120
|
+
|
|
121
|
+
str.split(/[\n&]/).filter_map do |pair|
|
|
122
|
+
pair = pair.strip
|
|
123
|
+
key, value = pair.split(delimiter_for(pair), 2)
|
|
119
124
|
next if value.nil?
|
|
120
125
|
|
|
121
|
-
|
|
122
|
-
end.
|
|
126
|
+
[key.strip, CGI.unescape_uri_component(value.strip)]
|
|
127
|
+
end.to_h
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
# ": " (not ":") so an "https://" URL isn't mistaken for a "Name: Value" header.
|
|
131
|
+
def delimiter_for(pair)
|
|
132
|
+
equals = pair.index('=')
|
|
133
|
+
colon = pair.index(': ')
|
|
134
|
+
return '=' if colon.nil?
|
|
135
|
+
return ': ' if equals.nil?
|
|
136
|
+
|
|
137
|
+
colon < equals ? ': ' : '='
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def json_to_hash(str)
|
|
141
|
+
parsed = JSON.parse(str)
|
|
142
|
+
parsed.is_a?(Hash) ? parsed.transform_values(&:to_s) : {}
|
|
143
|
+
rescue JSON::ParserError
|
|
144
|
+
{}
|
|
123
145
|
end
|
|
124
146
|
end
|
|
125
147
|
end
|
|
@@ -6,13 +6,14 @@ module TRMNLP
|
|
|
6
6
|
module Lint
|
|
7
7
|
module Checks
|
|
8
8
|
# Reports custom fields declared in .trmnlp.yml that never appear in the
|
|
9
|
-
# polling settings or the
|
|
9
|
+
# polling settings, the markup or the serverless transform — one finding
|
|
10
|
+
# per unused field.
|
|
10
11
|
class CustomFieldsUsed < Check
|
|
11
12
|
SETTINGS_KEYS = %w[polling_url polling_headers polling_body].freeze
|
|
12
13
|
|
|
13
14
|
def issues
|
|
14
15
|
source.custom_field_values.keys.reject { |keyname| used?(keyname) }.map do |keyname|
|
|
15
|
-
{ message: "Custom field '#{keyname}' is not used in form fields or
|
|
16
|
+
{ message: "Custom field '#{keyname}' is not used in form fields, markup or the transform." }
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
|
|
@@ -20,7 +21,8 @@ module TRMNLP
|
|
|
20
21
|
|
|
21
22
|
def used?(keyname)
|
|
22
23
|
pattern = /#{Regexp.escape(keyname)}/
|
|
23
|
-
searchable_settings.match?(pattern) || source.all_markup.match?(pattern)
|
|
24
|
+
searchable_settings.match?(pattern) || source.all_markup.match?(pattern) ||
|
|
25
|
+
source.transform_code.match?(pattern)
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def searchable_settings
|
data/lib/trmnlp/lint/source.rb
CHANGED
|
@@ -33,6 +33,15 @@ module TRMNLP
|
|
|
33
33
|
@all_markup ||= view_markup.values.join + shared_markup
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
# The serverless transform (src/transform.{py,rb,php,js}), or '' without one.
|
|
37
|
+
# It reads custom fields from its input, so a field may be used only there.
|
|
38
|
+
def transform_code
|
|
39
|
+
@transform_code ||= begin
|
|
40
|
+
path, = paths.transform_file
|
|
41
|
+
path ? read(path) : ''
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
36
45
|
private
|
|
37
46
|
|
|
38
47
|
attr_reader :config, :paths
|
data/lib/trmnlp/oauth/client.rb
CHANGED
|
@@ -39,9 +39,8 @@ module TRMNLP
|
|
|
39
39
|
)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
#
|
|
43
|
-
|
|
44
|
-
def auth_scheme = provider.client_secret ? :basic_auth : :request_body
|
|
42
|
+
# Same rule as the hosted service: HTTP Basic only when asked for, otherwise the body.
|
|
43
|
+
def auth_scheme = provider.token_request_auth_method == 'header' ? :basic_auth : :request_body
|
|
45
44
|
|
|
46
45
|
# oauth2 posts tokens through a connection built from the site, so give it
|
|
47
46
|
# the endpoint's origin even though the full URL is absolute.
|
|
@@ -19,6 +19,7 @@ module TRMNLP
|
|
|
19
19
|
def refresh_url = settings['oauth_refresh_url'] || token_url
|
|
20
20
|
def scopes = settings['oauth_scopes']
|
|
21
21
|
def scope_separator = settings['oauth_scope_separator'] || ' '
|
|
22
|
+
def token_request_auth_method = settings['oauth_token_request_auth_method']
|
|
22
23
|
def pkce? = truthy?(settings['oauth_pkce_enabled'])
|
|
23
24
|
def enabled? = truthy?(settings['oauth_enabled'])
|
|
24
25
|
def client_id = env_first(ENV_CLIENT_ID, settings['oauth_client_id'])
|
|
@@ -40,11 +40,19 @@ module TRMNLP
|
|
|
40
40
|
def run(path, inferred_language, data)
|
|
41
41
|
language = config.plugin.serverless_language || inferred_language
|
|
42
42
|
result = client.execute(code: path.read, stdin: JSON.generate(data), language:)
|
|
43
|
+
report_printed_output(result)
|
|
43
44
|
return record_failure(result, data) unless result.success?
|
|
44
45
|
|
|
45
46
|
parse_output(result.output, data)
|
|
46
47
|
end
|
|
47
48
|
|
|
49
|
+
# The transform's return value travels separately, so stdout holds only what it printed.
|
|
50
|
+
def report_printed_output(result)
|
|
51
|
+
{ 'stdout' => result.stdout, 'stderr' => result.stderr }.each do |stream, text|
|
|
52
|
+
reporter.info("transform #{stream}: #{text.strip}") unless text.strip.empty?
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
48
56
|
def record_failure(result, fallback)
|
|
49
57
|
@error = result.error || "transform exited #{result.exit_code}: #{result.stderr.strip}"
|
|
50
58
|
reporter.info("transform failed: #{@error}")
|
data/lib/trmnlp/version.rb
CHANGED