app_bridge 1.0.0-aarch64-linux → 2.1.0-aarch64-linux
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/.editorconfig +18 -0
- data/.tool-versions +1 -0
- data/Rakefile +6 -3
- data/ext/app_bridge/wit/world.wit +134 -15
- data/lib/app_bridge/3.2/app_bridge.so +0 -0
- data/lib/app_bridge/3.4/app_bridge.so +0 -0
- data/lib/app_bridge/app.rb +31 -3
- data/lib/app_bridge/version.rb +4 -1
- data/lib/app_bridge.rb +4 -6
- data/sig/app_bridge.rbs +26 -4
- data/tasks/fixtures.rake +15 -8
- data/tasks/rust_test.rake +11 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 33b5fa1a9b34b849616c293fd73e703f24f5178bec598bffe45a206ffaee5ee0
|
4
|
+
data.tar.gz: 59d6401d1a9524d982bdba6223b14318cc8e5d14a4898f66872eef4dd6e7a992
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 74288b43c3ab1b8a6fa6e7cb586772d3cdd221ab09144edea0b4318d7448d1aae4ac71bd389652f6fe6241efdfcddaffab628862596429d97724e45d0a872eb4
|
7
|
+
data.tar.gz: a3b26d26f4eafe732ce36f8e26be3d5ed4412cbd9a4c1e491d68a1f7a3a93937854deef1e471b896b3e20cbf4c9a2401dff373e7c1a5289a8f611e0b2a63164d
|
data/.editorconfig
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
# EditorConfig helps developers define and maintain consistent
|
2
|
+
# coding styles between different editors and IDEs
|
3
|
+
# http://editorconfig.org/
|
4
|
+
|
5
|
+
root = true
|
6
|
+
|
7
|
+
[*]
|
8
|
+
end_of_line = lf
|
9
|
+
trim_trailing_whitespace = true
|
10
|
+
insert_final_newline = true
|
11
|
+
charset = utf-8
|
12
|
+
indent_style = space
|
13
|
+
indent_size = 2
|
14
|
+
curly_bracket_next_line = false
|
15
|
+
indent_brace_style = K&R
|
16
|
+
|
17
|
+
[*.md]
|
18
|
+
trim_trailing_whitespace = false
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.4.2
|
data/Rakefile
CHANGED
@@ -3,8 +3,6 @@
|
|
3
3
|
require "bundler/gem_tasks"
|
4
4
|
require "rspec/core/rake_task"
|
5
5
|
|
6
|
-
RSpec::Core::RakeTask.new(:spec)
|
7
|
-
|
8
6
|
require "rubocop/rake_task"
|
9
7
|
|
10
8
|
RuboCop::RakeTask.new
|
@@ -22,4 +20,9 @@ end
|
|
22
20
|
# Load all project specific rake tasks
|
23
21
|
Dir.glob(File.expand_path("tasks/**/*.rake", __dir__)).each { |file| load file }
|
24
22
|
|
25
|
-
|
23
|
+
# Set test mode environment variable for specs
|
24
|
+
RSpec::Core::RakeTask.new(:spec) do |_t|
|
25
|
+
ENV["APP_BRIDGE_TEST_MODE"] = "1"
|
26
|
+
end
|
27
|
+
|
28
|
+
task default: %i[fixtures compile rust:test spec rubocop]
|
@@ -1,4 +1,4 @@
|
|
1
|
-
package standout:app@
|
1
|
+
package standout:app@2.1.0;
|
2
2
|
|
3
3
|
interface types {
|
4
4
|
// The trigger-store is a string that is used to store data between trigger
|
@@ -10,10 +10,10 @@ interface types {
|
|
10
10
|
// need to add more data to the store.
|
11
11
|
type trigger-store = string;
|
12
12
|
|
13
|
-
record
|
13
|
+
record connection {
|
14
14
|
id: string,
|
15
15
|
name: string,
|
16
|
-
// The
|
16
|
+
// The connection data is a JSON object serialized into a string. The JSON root
|
17
17
|
// will always be an object.
|
18
18
|
serialized-data: string,
|
19
19
|
}
|
@@ -23,12 +23,31 @@ interface types {
|
|
23
23
|
// invoked.
|
24
24
|
trigger-id: string,
|
25
25
|
|
26
|
-
// The
|
27
|
-
|
26
|
+
// The connection that the trigger is invoked for.
|
27
|
+
// Connection is required for all trigger operations.
|
28
|
+
connection: connection,
|
28
29
|
|
29
30
|
// The store will contain the data that was stored in the trigger store the
|
30
31
|
// last time the trigger was invoked.
|
31
32
|
store: trigger-store,
|
33
|
+
|
34
|
+
// The input data for the trigger, serialized as a JSON object string.
|
35
|
+
// This contains the input data from the trigger configuration form.
|
36
|
+
serialized-input: string,
|
37
|
+
}
|
38
|
+
|
39
|
+
record action-context {
|
40
|
+
// Action ID is a unique identifier for the action that is requested to be
|
41
|
+
// invoked.
|
42
|
+
action-id: string,
|
43
|
+
|
44
|
+
// The connection that the action is invoked for.
|
45
|
+
// Connection is required for all action operations.
|
46
|
+
connection: connection,
|
47
|
+
|
48
|
+
// The input data for the action, serialized as a JSON object string.
|
49
|
+
// This contains the data passed from the previous step in the workflow.
|
50
|
+
serialized-input: string,
|
32
51
|
}
|
33
52
|
|
34
53
|
record trigger-response {
|
@@ -41,10 +60,17 @@ interface types {
|
|
41
60
|
store: trigger-store,
|
42
61
|
}
|
43
62
|
|
63
|
+
record action-response {
|
64
|
+
// The output data from the action, serialized as a JSON object string.
|
65
|
+
// This contains the data that will be passed to the next step in the workflow.
|
66
|
+
// The data must be a valid JSON object (not an array or primitive).
|
67
|
+
serialized-output: string
|
68
|
+
}
|
69
|
+
|
44
70
|
record trigger-event {
|
45
71
|
// The ID of the trigger event
|
46
72
|
//
|
47
|
-
// If the
|
73
|
+
// If the connection used for the given instance of the trigger is the same,
|
48
74
|
// as seen before. Then the event will be ignored.
|
49
75
|
//
|
50
76
|
// A scheduler could therefore use an timestamp as the ID, to ensure that
|
@@ -59,24 +85,74 @@ interface types {
|
|
59
85
|
// ensure that the event is only triggered once per order update.
|
60
86
|
id: string,
|
61
87
|
|
62
|
-
// The timestamp of the event.
|
63
|
-
// Must be a unix timestamp in milliseconds since epoch (UTC).
|
64
|
-
// In JavaScript `Date.now()` can be used to get the current timestamp in
|
65
|
-
// milliseconds.
|
66
|
-
timestamp: u64,
|
67
|
-
|
68
88
|
// Serialized data must be a JSON object serialized into a string
|
69
89
|
// Note that it is important that the root is a object, not an array,
|
70
90
|
// or another primitive type.
|
71
91
|
serialized-data: string,
|
72
92
|
}
|
93
|
+
|
94
|
+
/// A structured error that can be returned by for example a call to a trigger or action.
|
95
|
+
/// Contains a machine-readable code and a human-readable message.
|
96
|
+
record app-error {
|
97
|
+
/// The error code identifying the type of failure.
|
98
|
+
code: error-code,
|
99
|
+
|
100
|
+
/// A human-readable message describing the error in more detail.
|
101
|
+
message: string,
|
102
|
+
}
|
103
|
+
|
104
|
+
/// An enumeration of error codes that can be returned by a trigger implementation.
|
105
|
+
/// These codes help the platform and plugin developers distinguish between different types of failures.
|
106
|
+
variant error-code {
|
107
|
+
/// Authentication failed. Typically due to an invalid or expired API key or token.
|
108
|
+
unauthenticated,
|
109
|
+
|
110
|
+
/// Authorization failed. The connection is valid but does not have the necessary permissions.
|
111
|
+
forbidden,
|
112
|
+
|
113
|
+
/// The trigger is misconfigured. For example, a required setting is missing or invalid.
|
114
|
+
misconfigured,
|
115
|
+
|
116
|
+
/// The target system does not support a required feature or endpoint.
|
117
|
+
unsupported,
|
118
|
+
|
119
|
+
/// The target system is rate-limiting requests. Try again later.
|
120
|
+
rate-limit,
|
121
|
+
|
122
|
+
/// The request timed out. The target system did not respond in time.
|
123
|
+
timeout,
|
124
|
+
|
125
|
+
/// The target system is currently unavailable or unreachable.
|
126
|
+
unavailable,
|
127
|
+
|
128
|
+
/// An unexpected internal error occurred in the plugin.
|
129
|
+
internal-error,
|
130
|
+
|
131
|
+
/// The response from the external system could not be parsed or was in an invalid format.
|
132
|
+
malformed-response,
|
133
|
+
|
134
|
+
/// A catch-all for all other types of errors. Should include a descriptive message.
|
135
|
+
other,
|
136
|
+
}
|
73
137
|
}
|
74
138
|
|
75
139
|
|
76
140
|
interface triggers {
|
77
|
-
use types.{trigger-context, trigger-event, trigger-response};
|
141
|
+
use types.{trigger-context, trigger-event, trigger-response, app-error};
|
142
|
+
|
143
|
+
trigger-ids: func() -> result<list<string>, app-error>;
|
78
144
|
|
79
|
-
|
145
|
+
// Get the input schema for a specific trigger
|
146
|
+
// Returns a JSON Schema Draft 2020-12 schema as a string
|
147
|
+
// The schema may vary based on the connection in the context
|
148
|
+
// The trigger-id is extracted from the context
|
149
|
+
input-schema: func(context: trigger-context) -> result<string, app-error>;
|
150
|
+
|
151
|
+
// Get the output schema for a specific trigger
|
152
|
+
// Returns a JSON Schema Draft 2020-12 schema as a string
|
153
|
+
// The schema may vary based on the connection in the context
|
154
|
+
// The trigger-id is extracted from the context
|
155
|
+
output-schema: func(context: trigger-context) -> result<string, app-error>;
|
80
156
|
|
81
157
|
// Fetch events
|
82
158
|
//
|
@@ -99,7 +175,48 @@ interface triggers {
|
|
99
175
|
// the same events. That will ensure that the user that is building an
|
100
176
|
// integration with your trigger will not miss any events if your system is
|
101
177
|
// down for a short period of time.
|
102
|
-
fetch-events: func(context: trigger-context) -> trigger-response
|
178
|
+
fetch-events: func(context: trigger-context) -> result<trigger-response, app-error>;
|
179
|
+
}
|
180
|
+
|
181
|
+
interface actions {
|
182
|
+
use types.{action-context, action-response, app-error};
|
183
|
+
|
184
|
+
action-ids: func() -> result<list<string>, app-error>;
|
185
|
+
|
186
|
+
// Get the input schema for a specific action
|
187
|
+
// Returns a JSON Schema Draft 2020-12 schema as a string
|
188
|
+
// The schema may vary based on the connection in the context
|
189
|
+
// The action-id is extracted from the context
|
190
|
+
input-schema: func(context: action-context) -> result<string, app-error>;
|
191
|
+
|
192
|
+
// Get the output schema for a specific action
|
193
|
+
// Returns a JSON Schema Draft 2020-12 schema as a string
|
194
|
+
// The schema may vary based on the connection in the context
|
195
|
+
// The action-id is extracted from the context
|
196
|
+
output-schema: func(context: action-context) -> result<string, app-error>;
|
197
|
+
|
198
|
+
// Execute an action
|
199
|
+
//
|
200
|
+
// There are some limitations to the function:
|
201
|
+
// - It must return an `action-response` within 30 seconds
|
202
|
+
// - The serialized-output must be a valid JSON object serialized as a string
|
203
|
+
//
|
204
|
+
// Actions can perform various operations such as:
|
205
|
+
// - Making HTTP requests to external APIs
|
206
|
+
// - Processing and transforming data
|
207
|
+
// - Storing data for future use
|
208
|
+
// - Triggering other systems or workflows
|
209
|
+
//
|
210
|
+
// The action receives input data from the previous step and can return
|
211
|
+
// serialized output data to be passed to the next step in the workflow.
|
212
|
+
execute: func(context: action-context) -> result<action-response, app-error>;
|
213
|
+
}
|
214
|
+
|
215
|
+
interface environment {
|
216
|
+
// Get all environment variables
|
217
|
+
env-vars: func() -> list<tuple<string, string>>;
|
218
|
+
// Get a specific environment variable by name
|
219
|
+
env-var: func(name: string) -> option<string>;
|
103
220
|
}
|
104
221
|
|
105
222
|
interface http {
|
@@ -154,5 +271,7 @@ interface http {
|
|
154
271
|
|
155
272
|
world bridge {
|
156
273
|
import http;
|
274
|
+
import environment;
|
157
275
|
export triggers;
|
276
|
+
export actions;
|
158
277
|
}
|
Binary file
|
Binary file
|
data/lib/app_bridge/app.rb
CHANGED
@@ -3,8 +3,16 @@
|
|
3
3
|
require "timeout"
|
4
4
|
|
5
5
|
module AppBridge
|
6
|
-
# An app that can be used to fetch events.
|
6
|
+
# An app that can be used to fetch events and execute actions.
|
7
7
|
class App
|
8
|
+
def initialize(component_path, environment_variables: {})
|
9
|
+
@component_path = component_path
|
10
|
+
@environment_variables = environment_variables
|
11
|
+
_rust_initialize(component_path, environment_variables)
|
12
|
+
rescue StandardError
|
13
|
+
raise InternalError, "Incompatible WASM file version"
|
14
|
+
end
|
15
|
+
|
8
16
|
def fetch_events(context)
|
9
17
|
response = request_events_with_timeout(context)
|
10
18
|
|
@@ -14,7 +22,15 @@ module AppBridge
|
|
14
22
|
response
|
15
23
|
end
|
16
24
|
|
17
|
-
def
|
25
|
+
def execute_action(context)
|
26
|
+
response = request_action_with_timeout(context)
|
27
|
+
|
28
|
+
validate_action_response_size!(response.serialized_output)
|
29
|
+
|
30
|
+
response
|
31
|
+
end
|
32
|
+
|
33
|
+
def timeout_seconds
|
18
34
|
30 # seconds
|
19
35
|
end
|
20
36
|
|
@@ -32,8 +48,20 @@ module AppBridge
|
|
32
48
|
raise StoreTooLargeError, "Store size exceeds 64 kB limit"
|
33
49
|
end
|
34
50
|
|
51
|
+
def validate_action_response_size!(serialized_output)
|
52
|
+
return if serialized_output.size <= 64 * 1024
|
53
|
+
|
54
|
+
raise ActionResponseTooLargeError, "Action response size exceeds 64 kB limit"
|
55
|
+
end
|
56
|
+
|
57
|
+
def request_action_with_timeout(context)
|
58
|
+
Timeout.timeout(timeout_seconds, TimeoutError, "Action exceeded #{timeout_seconds} seconds") do
|
59
|
+
_rust_execute_action(context)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
35
63
|
def request_events_with_timeout(context)
|
36
|
-
Timeout.timeout(
|
64
|
+
Timeout.timeout(timeout_seconds, TimeoutError, "Polling exceeded #{timeout_seconds} seconds") do
|
37
65
|
_rust_fetch_events(context)
|
38
66
|
end
|
39
67
|
end
|
data/lib/app_bridge/version.rb
CHANGED
data/lib/app_bridge.rb
CHANGED
@@ -3,17 +3,12 @@
|
|
3
3
|
require_relative "app_bridge/version"
|
4
4
|
require_relative "app_bridge/app"
|
5
5
|
|
6
|
-
begin
|
7
|
-
require "app_bridge/#{RUBY_VERSION.split(".").first(2).join(".")}/app_bridge"
|
8
|
-
rescue LoadError
|
9
|
-
require "app_bridge/app_bridge"
|
10
|
-
end
|
11
|
-
|
12
6
|
module AppBridge
|
13
7
|
class Error < StandardError; end
|
14
8
|
class TimeoutError < Error; end
|
15
9
|
class TooManyEventsError < Error; end
|
16
10
|
class StoreTooLargeError < Error; end
|
11
|
+
class ActionResponseTooLargeError < Error; end
|
17
12
|
|
18
13
|
# Represents a trigger event that is recieved from the app.
|
19
14
|
class TriggerEvent
|
@@ -23,3 +18,6 @@ module AppBridge
|
|
23
18
|
end
|
24
19
|
end
|
25
20
|
end
|
21
|
+
|
22
|
+
# Load the extension after the module is defined
|
23
|
+
require_relative "app_bridge/app_bridge"
|
data/sig/app_bridge.rbs
CHANGED
@@ -7,11 +7,15 @@ module AppBridge
|
|
7
7
|
|
8
8
|
def triggers: () -> Array[String]
|
9
9
|
|
10
|
+
def actions: () -> Array[String]
|
11
|
+
|
10
12
|
def fetch_events: (TriggerContext) -> TriggerResponse
|
13
|
+
|
14
|
+
def execute_action: (ActionContext) -> ActionResponse
|
11
15
|
end
|
12
16
|
|
13
|
-
class
|
14
|
-
def self.new: (String, String, String) ->
|
17
|
+
class Connection
|
18
|
+
def self.new: (String, String, String) -> Connection
|
15
19
|
|
16
20
|
def id: () -> String
|
17
21
|
|
@@ -39,12 +43,30 @@ module AppBridge
|
|
39
43
|
end
|
40
44
|
|
41
45
|
class TriggerContext
|
42
|
-
def self.new: (String,
|
46
|
+
def self.new: (String, Connection, String, String) -> TriggerContext
|
43
47
|
|
44
48
|
def trigger_id: () -> String
|
45
49
|
|
46
|
-
def
|
50
|
+
def connection: () -> Connection
|
47
51
|
|
48
52
|
def store: () -> String
|
53
|
+
|
54
|
+
def serialized_input: () -> String
|
55
|
+
end
|
56
|
+
|
57
|
+
class ActionContext
|
58
|
+
def self.new: (String, Connection, String) -> ActionContext
|
59
|
+
|
60
|
+
def action_id: () -> String
|
61
|
+
|
62
|
+
def connection: () -> Connection
|
63
|
+
|
64
|
+
def serialized_input: () -> String
|
65
|
+
end
|
66
|
+
|
67
|
+
class ActionResponse
|
68
|
+
def self.new: (String) -> ActionResponse
|
69
|
+
|
70
|
+
def serialized_output: () -> String
|
49
71
|
end
|
50
72
|
end
|
data/tasks/fixtures.rake
CHANGED
@@ -2,36 +2,43 @@
|
|
2
2
|
|
3
3
|
require "English"
|
4
4
|
|
5
|
-
namespace :fixtures do
|
5
|
+
namespace :fixtures do # rubocop:disable Metrics/BlockLength
|
6
6
|
namespace :apps do
|
7
7
|
desc "Clean up build artifacts"
|
8
8
|
task :clean do
|
9
|
-
# In context of the path spec/fixtures/components/
|
9
|
+
# In context of the path spec/fixtures/components/rust_app.
|
10
10
|
# Execute cargo clean.
|
11
11
|
#
|
12
|
-
pwd = "spec/fixtures/components/
|
12
|
+
pwd = "spec/fixtures/components/rust_app"
|
13
13
|
pid = Process.spawn("cargo clean", chdir: pwd)
|
14
14
|
Process.wait(pid)
|
15
15
|
raise "Failed to clean build artifacts" unless $CHILD_STATUS.success?
|
16
16
|
|
17
17
|
# Remove the built wasm artifact.
|
18
|
-
pid = Process.spawn("rm
|
18
|
+
pid = Process.spawn("rm rust_app.wasm", chdir: "spec/fixtures/components")
|
19
19
|
Process.wait(pid)
|
20
20
|
end
|
21
21
|
|
22
22
|
desc "Compile the fixture apps"
|
23
|
-
task :
|
24
|
-
pwd = "spec/fixtures/components/
|
23
|
+
task :compile_rust do
|
24
|
+
pwd = "spec/fixtures/components/rust_app"
|
25
25
|
compile_pid = Process.spawn("cargo clean && cargo build --release --target wasm32-wasip2",
|
26
26
|
chdir: pwd)
|
27
27
|
Process.wait(compile_pid)
|
28
28
|
raise "Failed to build artifacts" unless $CHILD_STATUS.success?
|
29
29
|
|
30
|
-
move_pid = Process.spawn("mv #{pwd}/target/wasm32-wasip2/release/
|
30
|
+
move_pid = Process.spawn("mv #{pwd}/target/wasm32-wasip2/release/rust_app.wasm #{pwd}/../rust_app.wasm")
|
31
31
|
Process.wait(move_pid)
|
32
32
|
end
|
33
|
+
|
34
|
+
task :compile_js do
|
35
|
+
pwd = "spec/fixtures/components/js_app"
|
36
|
+
pid = Process.spawn("npm run build", chdir: pwd)
|
37
|
+
Process.wait(pid)
|
38
|
+
raise "Failed to build artifacts" unless $CHILD_STATUS.success?
|
39
|
+
end
|
33
40
|
end
|
34
41
|
end
|
35
42
|
|
36
43
|
desc "Build all fixtures"
|
37
|
-
task fixtures: %i[fixtures:apps:clean fixtures:apps:
|
44
|
+
task fixtures: %i[fixtures:apps:clean fixtures:apps:compile_rust fixtures:apps:compile_js]
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: app_bridge
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 2.1.0
|
5
5
|
platform: aarch64-linux
|
6
6
|
authors:
|
7
7
|
- Alexander Ross
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-10-02 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: The app_bridge gem is designed to enable seamless interaction with WebAssembly
|
14
14
|
components that adhere to the WIT specification `standout:app`. It is developed
|
@@ -19,8 +19,10 @@ executables: []
|
|
19
19
|
extensions: []
|
20
20
|
extra_rdoc_files: []
|
21
21
|
files:
|
22
|
+
- ".editorconfig"
|
22
23
|
- ".rspec"
|
23
24
|
- ".rubocop.yml"
|
25
|
+
- ".tool-versions"
|
24
26
|
- CHANGELOG.md
|
25
27
|
- README.md
|
26
28
|
- Rakefile
|
@@ -32,6 +34,7 @@ files:
|
|
32
34
|
- lib/app_bridge/version.rb
|
33
35
|
- sig/app_bridge.rbs
|
34
36
|
- tasks/fixtures.rake
|
37
|
+
- tasks/rust_test.rake
|
35
38
|
homepage: https://github.com/standout/app_bridge
|
36
39
|
licenses: []
|
37
40
|
metadata:
|