app_bridge 3.0.0 → 4.1.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/.rubocop.yml +1 -0
- data/.tool-versions +1 -1
- data/Cargo.lock +292 -751
- data/Cargo.toml +1 -1
- data/README.md +274 -2
- data/ext/app_bridge/Cargo.toml +8 -4
- data/ext/app_bridge/src/app_state.rs +32 -13
- data/ext/app_bridge/src/component.rs +346 -45
- data/ext/app_bridge/src/error_mapping.rs +40 -24
- data/ext/app_bridge/src/file_ops.rs +326 -0
- data/ext/app_bridge/src/lib.rs +21 -3
- data/ext/app_bridge/src/request_builder.rs +343 -152
- data/ext/app_bridge/src/types.rs +95 -0
- data/ext/app_bridge/src/wrappers/action_context.rs +70 -9
- data/ext/app_bridge/src/wrappers/action_response.rs +7 -3
- data/ext/app_bridge/src/wrappers/app.rs +112 -148
- data/ext/app_bridge/src/wrappers/connection.rs +4 -4
- data/ext/app_bridge/src/wrappers/trigger_context.rs +7 -7
- data/ext/app_bridge/src/wrappers/trigger_event.rs +4 -4
- data/ext/app_bridge/src/wrappers/trigger_response.rs +29 -28
- data/ext/app_bridge/wit/{world.wit → v3/world.wit} +3 -0
- data/ext/app_bridge/wit/v4/world.wit +328 -0
- data/ext/app_bridge/wit/v4_1/world.wit +343 -0
- data/lib/app_bridge/app.rb +21 -2
- data/lib/app_bridge/file_processor.rb +131 -0
- data/lib/app_bridge/version.rb +1 -1
- data/lib/app_bridge.rb +25 -0
- data/tasks/fixtures.rake +16 -2
- metadata +9 -4
|
@@ -1,25 +1,338 @@
|
|
|
1
|
-
use std::result::Result::Ok;
|
|
2
1
|
use std::collections::HashMap;
|
|
3
|
-
use
|
|
2
|
+
use std::result::Result::Ok;
|
|
3
|
+
use wasmtime::component::{Component, Linker};
|
|
4
4
|
use wasmtime::{Engine, Result, Store};
|
|
5
|
-
use wasmtime_wasi::WasiCtxBuilder;
|
|
6
|
-
|
|
7
|
-
bindgen!({
|
|
8
|
-
path: "./wit",
|
|
9
|
-
world: "bridge",
|
|
10
|
-
});
|
|
5
|
+
use wasmtime_wasi::p2::WasiCtxBuilder;
|
|
11
6
|
|
|
12
7
|
use crate::app_state::AppState;
|
|
8
|
+
use crate::types::{
|
|
9
|
+
ActionContext, ActionResponse, AppError, Connection, ErrorCode, TriggerContext,
|
|
10
|
+
ReferenceObject, TriggerEvent, TriggerResponse,
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// WIT version modules
|
|
15
|
+
//
|
|
16
|
+
// To add a new version:
|
|
17
|
+
// 1. Add a new pub mod vN { bindgen!(...) }
|
|
18
|
+
// 2. Add impl_conversions!(vN) below
|
|
19
|
+
// 3. Add variant to BridgeWrapper enum
|
|
20
|
+
// 4. Add to build_linker() and app() functions
|
|
21
|
+
// 5. Add arm to each bridge_method! in BridgeWrapper impl
|
|
22
|
+
// ============================================================================
|
|
23
|
+
|
|
24
|
+
pub mod v3 {
|
|
25
|
+
wasmtime::component::bindgen!({
|
|
26
|
+
path: "./wit/v3",
|
|
27
|
+
world: "bridge",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
pub mod v4 {
|
|
32
|
+
wasmtime::component::bindgen!({
|
|
33
|
+
path: "./wit/v4",
|
|
34
|
+
world: "bridge",
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
pub mod v4_1 {
|
|
39
|
+
wasmtime::component::bindgen!({
|
|
40
|
+
path: "./wit/v4_1",
|
|
41
|
+
world: "bridge",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// Version conversion macro - generates From impls for a version module
|
|
47
|
+
// ============================================================================
|
|
48
|
+
|
|
49
|
+
macro_rules! impl_error_code_conversion {
|
|
50
|
+
($v:ident, $($extra_arms:tt)*) => {
|
|
51
|
+
impl From<$v::standout::app::types::ErrorCode> for ErrorCode {
|
|
52
|
+
fn from(c: $v::standout::app::types::ErrorCode) -> Self {
|
|
53
|
+
use $v::standout::app::types::ErrorCode as V;
|
|
54
|
+
match c {
|
|
55
|
+
V::Unauthenticated => Self::Unauthenticated,
|
|
56
|
+
V::Forbidden => Self::Forbidden,
|
|
57
|
+
V::Misconfigured => Self::Misconfigured,
|
|
58
|
+
V::Unsupported => Self::Unsupported,
|
|
59
|
+
V::RateLimit => Self::RateLimit,
|
|
60
|
+
V::Timeout => Self::Timeout,
|
|
61
|
+
V::Unavailable => Self::Unavailable,
|
|
62
|
+
V::InternalError => Self::InternalError,
|
|
63
|
+
V::MalformedResponse => Self::MalformedResponse,
|
|
64
|
+
V::Other => Self::Other,
|
|
65
|
+
$($extra_arms)*
|
|
66
|
+
V::CompleteWorkflow => Self::CompleteWorkflow,
|
|
67
|
+
V::CompleteParent => Self::CompleteParent,
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
macro_rules! impl_conversions {
|
|
75
|
+
($v:ident) => {
|
|
76
|
+
// TriggerEvent: version → canonical
|
|
77
|
+
impl From<$v::standout::app::types::TriggerEvent> for TriggerEvent {
|
|
78
|
+
fn from(e: $v::standout::app::types::TriggerEvent) -> Self {
|
|
79
|
+
Self { id: e.id, serialized_data: e.serialized_data }
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// TriggerResponse: version → canonical
|
|
84
|
+
impl From<$v::standout::app::types::TriggerResponse> for TriggerResponse {
|
|
85
|
+
fn from(r: $v::standout::app::types::TriggerResponse) -> Self {
|
|
86
|
+
Self {
|
|
87
|
+
store: r.store,
|
|
88
|
+
events: r.events.into_iter().map(Into::into).collect(),
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ActionResponse: version → canonical
|
|
94
|
+
impl From<$v::standout::app::types::ActionResponse> for ActionResponse {
|
|
95
|
+
fn from(r: $v::standout::app::types::ActionResponse) -> Self {
|
|
96
|
+
Self { serialized_output: r.serialized_output }
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Connection: canonical → version (for passing to components)
|
|
101
|
+
impl From<&Connection> for $v::standout::app::types::Connection {
|
|
102
|
+
fn from(c: &Connection) -> Self {
|
|
103
|
+
Self {
|
|
104
|
+
id: c.id.clone(),
|
|
105
|
+
name: c.name.clone(),
|
|
106
|
+
serialized_data: c.serialized_data.clone(),
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// TriggerContext: canonical → version
|
|
112
|
+
impl From<&TriggerContext> for $v::standout::app::types::TriggerContext {
|
|
113
|
+
fn from(c: &TriggerContext) -> Self {
|
|
114
|
+
Self {
|
|
115
|
+
trigger_id: c.trigger_id.clone(),
|
|
116
|
+
connection: (&c.connection).into(),
|
|
117
|
+
store: c.store.clone(),
|
|
118
|
+
serialized_input: c.serialized_input.clone(),
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
macro_rules! impl_app_error_conversion {
|
|
127
|
+
($v:ident) => {
|
|
128
|
+
impl From<$v::standout::app::types::AppError> for AppError {
|
|
129
|
+
fn from(e: $v::standout::app::types::AppError) -> Self {
|
|
130
|
+
Self {
|
|
131
|
+
code: e.code.into(),
|
|
132
|
+
message: e.message,
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
macro_rules! impl_action_context_conversion_basic {
|
|
140
|
+
($v:ident) => {
|
|
141
|
+
impl From<&ActionContext> for $v::standout::app::types::ActionContext {
|
|
142
|
+
fn from(c: &ActionContext) -> Self {
|
|
143
|
+
Self {
|
|
144
|
+
action_id: c.action_id.clone(),
|
|
145
|
+
connection: (&c.connection).into(),
|
|
146
|
+
serialized_input: c.serialized_input.clone(),
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
macro_rules! impl_action_context_conversion_retry {
|
|
154
|
+
($v:ident) => {
|
|
155
|
+
impl From<&ActionContext> for $v::standout::app::types::ActionContext {
|
|
156
|
+
fn from(c: &ActionContext) -> Self {
|
|
157
|
+
Self {
|
|
158
|
+
action_id: c.action_id.clone(),
|
|
159
|
+
connection: (&c.connection).into(),
|
|
160
|
+
serialized_input: c.serialized_input.clone(),
|
|
161
|
+
reference_object: c.reference_object.as_ref().map(Into::into),
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
impl From<v4_1::standout::app::types::ReferenceObject> for ReferenceObject {
|
|
169
|
+
fn from(r: v4_1::standout::app::types::ReferenceObject) -> Self {
|
|
170
|
+
Self {
|
|
171
|
+
reference: r.reference,
|
|
172
|
+
status: r.status,
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
impl From<&ReferenceObject> for v4_1::standout::app::types::ReferenceObject {
|
|
178
|
+
fn from(r: &ReferenceObject) -> Self {
|
|
179
|
+
Self {
|
|
180
|
+
reference: r.reference.clone(),
|
|
181
|
+
status: r.status.clone(),
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Generate conversions for all supported versions
|
|
187
|
+
impl_error_code_conversion!(v3,);
|
|
188
|
+
impl_conversions!(v3);
|
|
189
|
+
impl_app_error_conversion!(v3);
|
|
190
|
+
impl_action_context_conversion_basic!(v3);
|
|
191
|
+
impl_error_code_conversion!(v4,);
|
|
192
|
+
impl_conversions!(v4);
|
|
193
|
+
impl_app_error_conversion!(v4);
|
|
194
|
+
impl_action_context_conversion_basic!(v4);
|
|
195
|
+
impl_error_code_conversion!(
|
|
196
|
+
v4_1,
|
|
197
|
+
V::RetryWithReference(r) => Self::RetryWithReference(r.into()),
|
|
198
|
+
);
|
|
199
|
+
impl_conversions!(v4_1);
|
|
200
|
+
impl_app_error_conversion!(v4_1);
|
|
201
|
+
impl_action_context_conversion_retry!(v4_1);
|
|
202
|
+
|
|
203
|
+
// ============================================================================
|
|
204
|
+
// BridgeWrapper - unified interface for all component versions
|
|
205
|
+
//
|
|
206
|
+
// To add vN: add variant BridgeWrapper::VN(vN::Bridge)
|
|
207
|
+
// ============================================================================
|
|
208
|
+
|
|
209
|
+
pub enum BridgeWrapper {
|
|
210
|
+
V3(v3::Bridge),
|
|
211
|
+
V4(v4::Bridge),
|
|
212
|
+
V4_1(v4_1::Bridge),
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
impl BridgeWrapper {
|
|
216
|
+
/// Returns the WIT version this component was built against
|
|
217
|
+
pub fn wit_version(&self) -> &'static str {
|
|
218
|
+
match self {
|
|
219
|
+
BridgeWrapper::V3(_) => "3.0.0",
|
|
220
|
+
BridgeWrapper::V4(_) => "4.0.0",
|
|
221
|
+
BridgeWrapper::V4_1(_) => "4.1.0",
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/// Macro to implement a bridge method that works across all versions.
|
|
227
|
+
/// Each version's result is converted to canonical types.
|
|
228
|
+
macro_rules! bridge_method {
|
|
229
|
+
// Simple no-arg method (e.g., trigger_ids, action_ids)
|
|
230
|
+
(fn $name:ident() -> Result<$ok_type:ty> via $interface:ident . $method:ident) => {
|
|
231
|
+
pub fn $name(&self, store: &mut Store<AppState>) -> Result<std::result::Result<$ok_type, AppError>> {
|
|
232
|
+
match self {
|
|
233
|
+
BridgeWrapper::V3(b) => {
|
|
234
|
+
let r = b.$interface().$method(store)?;
|
|
235
|
+
Ok(r.map_err(Into::into))
|
|
236
|
+
}
|
|
237
|
+
BridgeWrapper::V4(b) => {
|
|
238
|
+
let r = b.$interface().$method(store)?;
|
|
239
|
+
Ok(r.map_err(Into::into))
|
|
240
|
+
}
|
|
241
|
+
BridgeWrapper::V4_1(b) => {
|
|
242
|
+
let r = b.$interface().$method(store)?;
|
|
243
|
+
Ok(r.map_err(Into::into))
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
// Method with TriggerContext
|
|
249
|
+
(fn $name:ident(&TriggerContext) -> Result<$ok_type:ty> via $interface:ident . $method:ident) => {
|
|
250
|
+
pub fn $name(&self, store: &mut Store<AppState>, ctx: &TriggerContext) -> Result<std::result::Result<$ok_type, AppError>> {
|
|
251
|
+
match self {
|
|
252
|
+
BridgeWrapper::V3(b) => {
|
|
253
|
+
let r = b.$interface().$method(store, &ctx.into())?;
|
|
254
|
+
Ok(r.map(Into::into).map_err(Into::into))
|
|
255
|
+
}
|
|
256
|
+
BridgeWrapper::V4(b) => {
|
|
257
|
+
let r = b.$interface().$method(store, &ctx.into())?;
|
|
258
|
+
Ok(r.map(Into::into).map_err(Into::into))
|
|
259
|
+
}
|
|
260
|
+
BridgeWrapper::V4_1(b) => {
|
|
261
|
+
let r = b.$interface().$method(store, &ctx.into())?;
|
|
262
|
+
Ok(r.map(Into::into).map_err(Into::into))
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
// Method with ActionContext
|
|
268
|
+
(fn $name:ident(&ActionContext) -> Result<$ok_type:ty> via $interface:ident . $method:ident) => {
|
|
269
|
+
pub fn $name(&self, store: &mut Store<AppState>, ctx: &ActionContext) -> Result<std::result::Result<$ok_type, AppError>> {
|
|
270
|
+
match self {
|
|
271
|
+
BridgeWrapper::V3(b) => {
|
|
272
|
+
let r = b.$interface().$method(store, &ctx.into())?;
|
|
273
|
+
Ok(r.map(Into::into).map_err(Into::into))
|
|
274
|
+
}
|
|
275
|
+
BridgeWrapper::V4(b) => {
|
|
276
|
+
let r = b.$interface().$method(store, &ctx.into())?;
|
|
277
|
+
Ok(r.map(Into::into).map_err(Into::into))
|
|
278
|
+
}
|
|
279
|
+
BridgeWrapper::V4_1(b) => {
|
|
280
|
+
let r = b.$interface().$method(store, &ctx.into())?;
|
|
281
|
+
Ok(r.map(Into::into).map_err(Into::into))
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
impl BridgeWrapper {
|
|
289
|
+
// Trigger methods
|
|
290
|
+
bridge_method!(fn call_trigger_ids() -> Result<Vec<String>> via standout_app_triggers . call_trigger_ids);
|
|
291
|
+
bridge_method!(fn call_trigger_input_schema(&TriggerContext) -> Result<String> via standout_app_triggers . call_input_schema);
|
|
292
|
+
bridge_method!(fn call_trigger_output_schema(&TriggerContext) -> Result<String> via standout_app_triggers . call_output_schema);
|
|
293
|
+
bridge_method!(fn call_fetch_events(&TriggerContext) -> Result<TriggerResponse> via standout_app_triggers . call_fetch_events);
|
|
294
|
+
|
|
295
|
+
// Action methods
|
|
296
|
+
bridge_method!(fn call_action_ids() -> Result<Vec<String>> via standout_app_actions . call_action_ids);
|
|
297
|
+
bridge_method!(fn call_action_input_schema(&ActionContext) -> Result<String> via standout_app_actions . call_input_schema);
|
|
298
|
+
bridge_method!(fn call_action_output_schema(&ActionContext) -> Result<String> via standout_app_actions . call_output_schema);
|
|
299
|
+
bridge_method!(fn call_execute(&ActionContext) -> Result<ActionResponse> via standout_app_actions . call_execute);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// ============================================================================
|
|
303
|
+
// Builder functions
|
|
304
|
+
// ============================================================================
|
|
13
305
|
|
|
14
306
|
pub fn build_engine() -> Engine {
|
|
15
307
|
Engine::default()
|
|
16
308
|
}
|
|
17
309
|
|
|
18
310
|
pub fn build_linker(engine: &Engine) -> Result<Linker<AppState>> {
|
|
19
|
-
let mut linker = Linker::<AppState>::new(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
311
|
+
let mut linker = Linker::<AppState>::new(engine);
|
|
312
|
+
|
|
313
|
+
// WASI support (shared by all versions)
|
|
314
|
+
wasmtime_wasi::p2::add_to_linker_sync(&mut linker)?;
|
|
315
|
+
|
|
316
|
+
// ---- Version-specific interfaces ----
|
|
317
|
+
// v3: http + environment
|
|
318
|
+
v3::standout::app::http::add_to_linker(&mut linker, |s| s)?;
|
|
319
|
+
v3::standout::app::environment::add_to_linker(&mut linker, |s| s)?;
|
|
320
|
+
|
|
321
|
+
// v4: http + environment + file
|
|
322
|
+
v4::standout::app::http::add_to_linker(&mut linker, |s| s)?;
|
|
323
|
+
v4::standout::app::environment::add_to_linker(&mut linker, |s| s)?;
|
|
324
|
+
v4::standout::app::file::add_to_linker(&mut linker, |s| s)?;
|
|
325
|
+
|
|
326
|
+
// v4.1: http + environment + file
|
|
327
|
+
v4_1::standout::app::http::add_to_linker(&mut linker, |s| s)?;
|
|
328
|
+
v4_1::standout::app::environment::add_to_linker(&mut linker, |s| s)?;
|
|
329
|
+
v4_1::standout::app::file::add_to_linker(&mut linker, |s| s)?;
|
|
330
|
+
|
|
331
|
+
// Add new versions here:
|
|
332
|
+
// v5::standout::app::http::add_to_linker(&mut linker, |s| s)?;
|
|
333
|
+
// v5::standout::app::environment::add_to_linker(&mut linker, |s| s)?;
|
|
334
|
+
// v5::standout::app::file::add_to_linker(&mut linker, |s| s)?;
|
|
335
|
+
// v5::standout::app::new_feature::add_to_linker(&mut linker, |s| s)?;
|
|
23
336
|
|
|
24
337
|
Ok(linker)
|
|
25
338
|
}
|
|
@@ -27,54 +340,42 @@ pub fn build_linker(engine: &Engine) -> Result<Linker<AppState>> {
|
|
|
27
340
|
pub fn build_store(engine: &Engine, env_vars: Option<HashMap<String, String>>) -> Store<AppState> {
|
|
28
341
|
let mut builder = WasiCtxBuilder::new();
|
|
29
342
|
|
|
30
|
-
// Add environment variables to WASI context if provided
|
|
31
343
|
if let Some(env_vars) = &env_vars {
|
|
32
344
|
for (key, value) in env_vars {
|
|
33
345
|
builder.env(key, value);
|
|
34
346
|
}
|
|
35
347
|
}
|
|
36
348
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
// Create AppState with or without environment variables
|
|
40
|
-
let app_state = AppState::new(ctx, env_vars);
|
|
41
|
-
|
|
42
|
-
Store::new(&engine, app_state)
|
|
349
|
+
Store::new(engine, AppState::new(builder.build(), env_vars))
|
|
43
350
|
}
|
|
44
351
|
|
|
352
|
+
/// Try to instantiate a WASM component.
|
|
353
|
+
/// Attempts versions from newest to oldest until one succeeds.
|
|
45
354
|
pub fn app(
|
|
46
355
|
file_path: String,
|
|
47
356
|
engine: Engine,
|
|
48
357
|
store: &mut Store<AppState>,
|
|
49
358
|
linker: Linker<AppState>,
|
|
50
|
-
) -> Result<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
//
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
Ok(instance) => Ok(instance),
|
|
58
|
-
Err(e) => {
|
|
59
|
-
if e.to_string().contains("no exported instance") {
|
|
60
|
-
Err(wasmtime::Error::msg(
|
|
61
|
-
"Incompatible WASM file version"
|
|
62
|
-
))
|
|
63
|
-
} else {
|
|
64
|
-
Err(e)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
359
|
+
) -> Result<BridgeWrapper> {
|
|
360
|
+
let component = Component::from_file(&engine, &file_path)?;
|
|
361
|
+
|
|
362
|
+
// Try versions newest-first. When adding vN, insert at the top.
|
|
363
|
+
// v4.1 (current - has file interface)
|
|
364
|
+
if let Ok(instance) = v4_1::Bridge::instantiate(&mut *store, &component, &linker) {
|
|
365
|
+
return Ok(BridgeWrapper::V4_1(instance));
|
|
67
366
|
}
|
|
68
|
-
}
|
|
69
367
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
let mut store = build_store(&engine, None);
|
|
75
|
-
let linker = build_linker(&engine).unwrap();
|
|
76
|
-
let instant = app(file_path.to_string(), engine, &mut store, linker);
|
|
368
|
+
// v4
|
|
369
|
+
if let Ok(instance) = v4::Bridge::instantiate(&mut *store, &component, &linker) {
|
|
370
|
+
return Ok(BridgeWrapper::V4(instance));
|
|
371
|
+
}
|
|
77
372
|
|
|
78
|
-
|
|
373
|
+
// v3 (legacy - no file interface)
|
|
374
|
+
if let Ok(instance) = v3::Bridge::instantiate(&mut *store, &component, &linker) {
|
|
375
|
+
return Ok(BridgeWrapper::V3(instance));
|
|
79
376
|
}
|
|
377
|
+
|
|
378
|
+
Err(wasmtime::Error::msg(
|
|
379
|
+
"Failed to instantiate component: no compatible WIT version found (tried v4.1, v4, v3)",
|
|
380
|
+
))
|
|
80
381
|
}
|
|
@@ -1,32 +1,48 @@
|
|
|
1
|
-
use crate::
|
|
2
|
-
use magnus::
|
|
1
|
+
use crate::types::{AppError, ErrorCode};
|
|
2
|
+
use magnus::prelude::*;
|
|
3
|
+
use magnus::{Error, ExceptionClass, RObject, Ruby};
|
|
3
4
|
|
|
4
5
|
impl From<ErrorCode> for ExceptionClass {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
fn from(value: ErrorCode) -> Self {
|
|
7
|
+
fn get_class(name: &str) -> ExceptionClass {
|
|
8
|
+
let ruby = Ruby::get().unwrap();
|
|
9
|
+
ruby.eval::<ExceptionClass>(name).unwrap()
|
|
10
|
+
}
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
12
|
+
match value {
|
|
13
|
+
ErrorCode::Unauthenticated => get_class("AppBridge::UnauthenticatedError"),
|
|
14
|
+
ErrorCode::Forbidden => get_class("AppBridge::ForbiddenError"),
|
|
15
|
+
ErrorCode::Misconfigured => get_class("AppBridge::MisconfiguredError"),
|
|
16
|
+
ErrorCode::Unsupported => get_class("AppBridge::UnsupportedError"),
|
|
17
|
+
ErrorCode::RateLimit => get_class("AppBridge::RateLimitError"),
|
|
18
|
+
ErrorCode::Timeout => get_class("AppBridge::TimeoutError"),
|
|
19
|
+
ErrorCode::Unavailable => get_class("AppBridge::UnavailableError"),
|
|
20
|
+
ErrorCode::InternalError => get_class("AppBridge::InternalError"),
|
|
21
|
+
ErrorCode::MalformedResponse => get_class("AppBridge::MalformedResponseError"),
|
|
22
|
+
ErrorCode::Other => get_class("AppBridge::OtherError"),
|
|
23
|
+
ErrorCode::RetryWithReference(_) => get_class("AppBridge::RetryWithReferenceError"),
|
|
24
|
+
ErrorCode::CompleteWorkflow => get_class("AppBridge::CompleteWorkflowException"),
|
|
25
|
+
ErrorCode::CompleteParent => get_class("AppBridge::CompleteParentException"),
|
|
26
|
+
}
|
|
24
27
|
}
|
|
25
|
-
}
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
impl From<AppError> for Error {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
fn from(value: AppError) -> Self {
|
|
32
|
+
if let ErrorCode::RetryWithReference(retry) = value.code.clone() {
|
|
33
|
+
let class: ExceptionClass = value.code.into();
|
|
34
|
+
let message = value.message;
|
|
35
|
+
if let Ok(exception) = class.new_instance((message.as_str(),)) {
|
|
36
|
+
if let Ok(exception_value) = RObject::try_convert(exception.as_value()) {
|
|
37
|
+
let _ = exception_value.ivar_set("@reference", retry.reference);
|
|
38
|
+
let _ = exception_value.ivar_set("@status", retry.status);
|
|
39
|
+
}
|
|
40
|
+
return Error::from(exception);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return Error::new(class, message);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
Error::new(value.code.into(), value.message)
|
|
47
|
+
}
|
|
32
48
|
}
|