mawsitsit 0.1.12 → 0.1.14

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.
@@ -1,9 +1,10 @@
1
- use serde_json::Value;
1
+ use serde_json::{Map, Value};
2
2
  use async_recursion::async_recursion;
3
3
  use serde::{Serialize, Deserialize};
4
4
  use serde_magnus::serialize;
5
5
  use magnus::Value as RubyValue;
6
- use crate::parser::manipulators::{like_enum, like_fetch, like_lambda, like_ashby};
6
+ use crate::parser::manipulators::{like_enum, like_fetch, like_lambda, like_ashby, like_lever, int_to_dt};
7
+ use super::{manipulators::EnumValue, utils::helpers::{remove_nulls, remove_nulls_in_place, vec_str}};
7
8
 
8
9
 
9
10
  #[derive(Serialize, Deserialize, PartialEq, Debug)]
@@ -15,6 +16,9 @@ impl JsonValue {
15
16
  pub fn new(value: serde_json::Value) -> JsonValue {
16
17
  JsonValue { value }
17
18
  }
19
+ pub fn null() -> JsonValue {
20
+ JsonValue { value: serde_json::Value::Null }
21
+ }
18
22
  pub fn get_by_path(&self, path: &str) -> Option<&Value> {
19
23
  let mut current = &self.value;
20
24
  for key in path.split('.') {
@@ -58,6 +62,15 @@ impl JsonValue {
58
62
  let ruby : RubyValue = serialize(&self.value).unwrap();
59
63
  return ruby;
60
64
  }
65
+ pub fn no_null(&self) -> JsonValue{
66
+ JsonValue {
67
+ value: remove_nulls(&self.value),
68
+ }
69
+ }
70
+ pub fn drop_nulls(&mut self) {
71
+ remove_nulls_in_place(&mut self.value);
72
+ }
73
+
61
74
 
62
75
  }
63
76
 
@@ -117,23 +130,100 @@ impl JsonToJson {
117
130
  let mut task_res = serde_json::Value::Null;
118
131
  match task.get(0) {
119
132
  Some(&"enum") => {
120
- task_res =
121
- like_enum(&reference.get_by_path(bin[0]).expect("Path not found in reference").to_string(), task.get(1).unwrap());
133
+ task_res = match reference.get_by_path(bin[0]) {
134
+ Some(value) => {
135
+ match task.get(1) {
136
+ Some(todo) => {
137
+ match value {
138
+ serde_json::Value::String(value_str) => like_enum(EnumValue::Str(value_str.to_string()), todo),
139
+ serde_json::Value::Bool(value_bool) => like_enum(EnumValue::Bool(*value_bool), todo),
140
+ _ => serde_json::Value::Null,
141
+ }
142
+ }
143
+
144
+ None => serde_json::Value::Null
145
+ }
146
+ },
147
+ None => serde_json::Value::Null
148
+ }
122
149
  }
123
150
  Some(&"fetch") => {
124
- task_res = like_fetch(&reference.get_by_path(bin[0]).expect("Path not found in reference").to_string(), task.get(1).unwrap()).await;
151
+ task_res = match reference.get_by_path(bin[0]) {
152
+ Some(value) => {
153
+ match task.get(1) {
154
+ Some(todo) => match value.as_str() {
155
+ Some(value) => like_fetch(value, todo).await,
156
+ None => serde_json::Value::Null
157
+ }
158
+ None => serde_json::Value::Null
159
+ }
160
+ },
161
+ None => serde_json::Value::Null
162
+ }
125
163
  }
126
164
  Some(&"ashby") => {
127
- task_res = like_ashby(&reference.get_by_path(bin[0]).expect("Path not found in reference"));
165
+ task_res = match reference.get_by_path(bin[0]) {
166
+ Some(value) => like_ashby(value),
167
+ None => serde_json::Value::Null
168
+ }
169
+
170
+ }
171
+ Some(&"lever") => {
172
+ task_res = match reference.get_by_path(bin[0]) {
173
+ Some(value) => like_lever(value),
174
+ None => serde_json::Value::Null
175
+ }
128
176
  }
129
177
  Some(&"lambda") => {
130
- task_res = like_lambda(&reference.get_by_path(bin[0]).expect("Path not found in reference").to_string(), task.get(1).unwrap());
178
+ task_res = match reference.get_by_path(bin[0]) {
179
+ Some(value) => {
180
+ match task.get(1) {
181
+ Some(todo) => match value.as_str() {
182
+ Some(value) => like_lambda(value, todo),
183
+ None => serde_json::Value::Null
184
+ }
185
+ None => serde_json::Value::Null
186
+ }
187
+ },
188
+ None => serde_json::Value::Null
189
+ }
190
+
191
+ }
192
+ Some(&"int_to_datetime") => {
193
+ task_res = match reference.get_by_path(bin[0]) {
194
+ Some(value) => {
195
+ match value.as_i64() {
196
+ Some(value) => int_to_dt(value),
197
+ None => serde_json::Value::Null
198
+ }
199
+ },
200
+ None => serde_json::Value::Null
201
+ }
202
+
203
+ }
204
+ Some(&"flatten") => {
205
+ task_res = reference.get_by_path(bin[0])
206
+ .and_then(|value| value.as_array())
207
+ .map_or(serde_json::Value::Null, |array| {
208
+ let strings: Vec<&str> = array.iter()
209
+ .filter_map(|v| v.as_str())
210
+ .collect();
211
+ serde_json::Value::String(vec_str(strings, ", "))
212
+ });
213
+
131
214
  }
132
215
  _ => (),
133
216
  }
134
217
  *value = task_res;
135
218
  } else {
136
- *value = reference.get_by_path(value_str).unwrap().clone();
219
+ let bin_spl:Vec<&str>= bin[0].split(".").collect();
220
+ if bin_spl[0] == "ignore" {
221
+ *value = bin[0].clone().into();
222
+ return;
223
+ }
224
+ *value = reference
225
+ .get_by_path(value_str)
226
+ .map_or_else(|| serde_json::Value::Null, |v| v.clone().into());
137
227
  }
138
228
  }
139
229
  }
@@ -1,5 +1,5 @@
1
1
  use std::fmt;
2
- use serde_json::{json, Value};
2
+ use serde_json::Value;
3
3
 
4
4
 
5
5
  #[derive(Debug)]
@@ -9,7 +9,7 @@ pub enum ParseError {
9
9
 
10
10
  impl fmt::Display for ParseError {
11
11
  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
12
- write!(f, "Ashby Application Option Type is not represented in QuestionType")
12
+ write!(f, "Application Option Type is not represented in QuestionType")
13
13
  }
14
14
  }
15
15
  impl std::error::Error for ParseError {}
@@ -86,6 +86,19 @@ pub fn parse_ashby_type(input: &str) -> Result<QuestionType, ParseError> {
86
86
  }
87
87
  }
88
88
 
89
+ pub fn parse_lever_type(input: &str) -> Result<QuestionType, ParseError> {
90
+ match input {
91
+ "text" => Ok(QuestionType::ShortText),
92
+ "file-upload" => Ok(QuestionType::File),
93
+ "textarea" => Ok(QuestionType::LongText),
94
+ "dropdown" => Ok(QuestionType::SingleChoice),
95
+ "multiple-choice" => Ok(QuestionType::SingleChoice),
96
+ "university" => Ok(QuestionType::SingleChoice),
97
+ "multiple-select" => Ok(QuestionType::MultipleChoice),
98
+ _ => Err(ParseError::InvalidType),
99
+ }
100
+ }
101
+
89
102
  #[derive(Debug)]
90
103
  pub struct ApplicationOption {
91
104
  pub question: String,
@@ -1,11 +1,16 @@
1
1
  use reqwest::{Client, Method};
2
2
  use std::collections::HashMap;
3
- use base64::encode;
4
3
  use magnus::Value as RubyValue;
4
+ use serde_json::{Map, Value as SerdeValue};
5
+
6
+
5
7
 
6
8
 
7
9
  pub fn str_vec<'a>(args: &'a str, param: &str) -> Vec<&'a str> {
8
- return args.split(param).collect();
10
+ args.split(param).collect()
11
+ }
12
+ pub fn vec_str(args: Vec<&str>, separator: &str) -> String {
13
+ args.join(separator)
9
14
  }
10
15
 
11
16
  pub async fn fetch(
@@ -19,11 +24,8 @@ pub async fn fetch(
19
24
  let mut request = client.request(method, url);
20
25
  request = request.header("accept", "application/json")
21
26
  .header("content-type", "application/json");
22
-
23
27
  request = request.body(serde_json::to_string(&input)?);
24
-
25
-
26
- let auth_header = format!("Basic {}", encode(api_key));
28
+ let auth_header = format!("Basic {}", api_key);
27
29
  request = request.header("authorization", auth_header);
28
30
  let response = request.send().await?;
29
31
  let json = response.json().await?;
@@ -34,8 +36,57 @@ pub trait IO {
34
36
  fn to_ruby(&self) -> RubyValue;
35
37
  }
36
38
 
39
+ pub fn remove_nulls(value: &SerdeValue) -> SerdeValue {
40
+ match value {
41
+ SerdeValue::Object(map) => {
42
+ let filtered_map: Map<_, _> = map.iter()
43
+ .filter_map(|(k, v)| {
44
+ let cleaned_value = remove_nulls(v);
45
+ if !cleaned_value.is_null() {
46
+ Some((k.clone(), cleaned_value))
47
+ } else {
48
+ None
49
+ }
50
+ })
51
+ .collect();
52
+ SerdeValue::Object(filtered_map)
53
+ }
54
+ SerdeValue::Array(arr) => {
55
+ let filtered_array: Vec<_> = arr.iter()
56
+ .map(|v| remove_nulls(v))
57
+ .filter(|v| !v.is_null())
58
+ .collect();
59
+ SerdeValue::Array(filtered_array)
60
+ }
61
+ _ => value.clone(),
62
+ }
63
+ }
37
64
 
38
-
39
-
40
-
41
-
65
+ pub fn remove_nulls_in_place(value: &mut serde_json::Value) {
66
+ match value {
67
+ serde_json::Value::Array(arr) => {
68
+ let mut i = 0;
69
+ while i < arr.len() {
70
+ if arr[i].is_null() {
71
+ arr.remove(i);
72
+ } else {
73
+ remove_nulls_in_place(&mut arr[i]);
74
+ i += 1;
75
+ }
76
+ }
77
+ }
78
+ serde_json::Value::Object(obj) => {
79
+ let keys: Vec<_> = obj.keys().cloned().collect();
80
+ for key in keys {
81
+ if let Some(v) = obj.get_mut(&key) {
82
+ if v.is_null() {
83
+ obj.remove(&key);
84
+ } else {
85
+ remove_nulls_in_place(v);
86
+ }
87
+ }
88
+ }
89
+ }
90
+ _ => {}
91
+ }
92
+ }
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Mawsitsit
4
- VERSION = "0.1.12"
4
+ VERSION = "0.1.14"
5
5
  end
@@ -0,0 +1,2 @@
1
+ [ZoneTransfer]
2
+ ZoneId=3
@@ -0,0 +1,333 @@
1
+
2
+ {
3
+ "data": {
4
+ "id": "54d15a33-c024-4ba4-bc62-6f9588978758",
5
+ "text": "test",
6
+ "customQuestions": [
7
+ {
8
+ "id": "911f7ca4-e7a2-4081-9472-0c1f94d9df25",
9
+ "text": "Custom Questions",
10
+ "fields": [
11
+ {
12
+ "description": "",
13
+ "required": true,
14
+ "text": "Short text",
15
+ "type": "text",
16
+ "id": "e7ac71d9-78e2-403a-a541-6c1802ee21e6",
17
+ "value": null
18
+ },
19
+ {
20
+ "description": "",
21
+ "required": true,
22
+ "text": "Long text",
23
+ "type": "textarea",
24
+ "id": "5844afad-6f34-47a1-bf69-b099e48db9c7",
25
+ "value": null
26
+ },
27
+ {
28
+ "description": "",
29
+ "required": true,
30
+ "text": "Dropdown",
31
+ "type": "dropdown",
32
+ "id": "5c89bddd-7aa7-430f-9db7-98ba78a524a9",
33
+ "prompt": "Choose one",
34
+ "options": [
35
+ {
36
+ "text": "Choice 1",
37
+ "optionId": "b0e17be1-c39f-4899-8fc5-a0b74b230371"
38
+ },
39
+ {
40
+ "text": "Choice 2",
41
+ "optionId": "d36aec06-c439-4832-8982-11e9c29bcb54"
42
+ },
43
+ {
44
+ "text": "Choice 3",
45
+ "optionId": "c1a6f7e3-bfeb-436d-8c78-08f08d7353f1"
46
+ },
47
+ {
48
+ "text": "Choice 4",
49
+ "optionId": "0a5fc73b-d775-4d31-8b7f-fb19a852c59d"
50
+ }
51
+ ],
52
+ "value": null
53
+ },
54
+ {
55
+ "description": "",
56
+ "required": true,
57
+ "text": "File upload",
58
+ "type": "file-upload",
59
+ "id": "4d1e49c2-1619-4216-9245-7f69c63b400d",
60
+ "value": null
61
+ },
62
+ {
63
+ "description": "",
64
+ "required": true,
65
+ "text": "Single Choice",
66
+ "type": "multiple-select",
67
+ "id": "4b3898d9-6dfa-4602-874a-dbe31fc8945c",
68
+ "options": [
69
+ {
70
+ "text": "Option1",
71
+ "optionId": "ff2e4a8a-0736-444f-b950-c4ab2c749973"
72
+ },
73
+ {
74
+ "text": "Option2",
75
+ "optionId": "f6f58997-2fa2-485f-85fd-fdb840913120"
76
+ }
77
+ ],
78
+ "value": []
79
+ },
80
+ {
81
+ "description": "",
82
+ "required": true,
83
+ "text": "Multiple Choice",
84
+ "type": "multiple-choice",
85
+ "id": "d9cf6785-2452-44bf-9eba-6854b68863c2",
86
+ "options": [
87
+ {
88
+ "text": "MC1",
89
+ "optionId": "0dab75d4-b915-4838-b764-c546a30f50e8"
90
+ },
91
+ {
92
+ "text": "MC2",
93
+ "optionId": "b4d057f0-5b4f-4182-b060-8147e670b4f9"
94
+ },
95
+ {
96
+ "text": "MC3",
97
+ "optionId": "7be4a1c6-ea29-41c6-b5c7-57b687341885"
98
+ }
99
+ ],
100
+ "value": null
101
+ }
102
+ ],
103
+ "distribution": [
104
+ "external"
105
+ ]
106
+ }
107
+ ],
108
+ "personalInformation": [
109
+ {
110
+ "text": "Full name",
111
+ "name": "fullName",
112
+ "type": "text",
113
+ "required": true,
114
+ "value": null
115
+ },
116
+ {
117
+ "text": "Email",
118
+ "name": "email",
119
+ "type": "text",
120
+ "required": true,
121
+ "value": null
122
+ },
123
+ {
124
+ "text": "Current company",
125
+ "name": "currentCompany",
126
+ "type": "text",
127
+ "required": false,
128
+ "value": null
129
+ },
130
+ {
131
+ "text": "Current location",
132
+ "name": "currentLocation",
133
+ "type": "text",
134
+ "required": true,
135
+ "value": null
136
+ },
137
+ {
138
+ "text": "Phone",
139
+ "name": "phone",
140
+ "type": "text",
141
+ "required": false,
142
+ "value": null
143
+ },
144
+ {
145
+ "text": "Resume",
146
+ "name": "resume",
147
+ "type": "file-upload",
148
+ "required": false,
149
+ "value": null
150
+ },
151
+ {
152
+ "text": "Additional information",
153
+ "name": "additionalInformation",
154
+ "type": "textarea",
155
+ "required": false,
156
+ "value": null
157
+ }
158
+ ],
159
+ "urls": [
160
+ {
161
+ "text": "LinkedIn",
162
+ "name": "LinkedIn",
163
+ "type": "text",
164
+ "required": false,
165
+ "value": null
166
+ },
167
+ {
168
+ "text": "Twitter",
169
+ "name": "Twitter",
170
+ "type": "text",
171
+ "required": false,
172
+ "value": null
173
+ },
174
+ {
175
+ "text": "GitHub",
176
+ "name": "GitHub",
177
+ "type": "text",
178
+ "required": false,
179
+ "value": null
180
+ },
181
+ {
182
+ "text": "Portfolio",
183
+ "name": "Portfolio",
184
+ "type": "text",
185
+ "required": false,
186
+ "value": null
187
+ },
188
+ {
189
+ "text": "Other",
190
+ "name": "Other",
191
+ "type": "text",
192
+ "required": false,
193
+ "value": null
194
+ }
195
+ ],
196
+ "consentDisclosures": null,
197
+ "eeoQuestions": {
198
+ "gender": {
199
+ "description": null,
200
+ "required": false,
201
+ "text": "Gender",
202
+ "type": "dropdown",
203
+ "options": [
204
+ {
205
+ "text": "Female",
206
+ "optionId": "Female"
207
+ },
208
+ {
209
+ "text": "Male",
210
+ "optionId": "Male"
211
+ },
212
+ {
213
+ "text": "Decline to self-identify",
214
+ "optionId": "Decline to self-identify"
215
+ }
216
+ ],
217
+ "prompt": "Gender",
218
+ "value": null
219
+ },
220
+ "race": {
221
+ "description": null,
222
+ "required": false,
223
+ "text": "Race",
224
+ "type": "dropdown",
225
+ "options": [
226
+ {
227
+ "text": "Hispanic or Latino",
228
+ "optionId": "Hispanic or Latino",
229
+ "description": "A person of Cuban, Mexican, Puerto Rican, South or Central American, or other Spanish culture or origin regardless of race."
230
+ },
231
+ {
232
+ "text": "White (Not Hispanic or Latino)",
233
+ "optionId": "White (Not Hispanic or Latino)",
234
+ "description": "A person having origins in any of the original peoples of Europe, the Middle East, or North Africa."
235
+ },
236
+ {
237
+ "text": "Black or African American (Not Hispanic or Latino)",
238
+ "optionId": "Black or African American (Not Hispanic or Latino)",
239
+ "description": "A person having origins in any of the black racial groups of Africa."
240
+ },
241
+ {
242
+ "text": "Native Hawaiian or Other Pacific Islander (Not Hispanic or Latino)",
243
+ "optionId": "Native Hawaiian or Other Pacific Islander (Not Hispanic or Latino)",
244
+ "description": "A person having origins in any of the peoples of Hawaii, Guam, Samoa, or other Pacific Islands."
245
+ },
246
+ {
247
+ "text": "Asian (Not Hispanic or Latino)",
248
+ "optionId": "Asian (Not Hispanic or Latino)",
249
+ "description": "A person having origins in any of the original peoples of the Far East, Southeast Asia, or the Indian Subcontinent, including, for example, Cambodia, China, India, Japan, Korea, Malaysia, Pakistan, the Philippine Islands, Thailand, and Vietnam."
250
+ },
251
+ {
252
+ "text": "American Indian or Alaska Native (Not Hispanic or Latino)",
253
+ "optionId": "American Indian or Alaska Native (Not Hispanic or Latino)",
254
+ "description": "A person having origins in any of the original peoples of North and South America (including Central America), and who maintain tribal affiliation or community attachment."
255
+ },
256
+ {
257
+ "text": "Two or More Races (Not Hispanic or Latino)",
258
+ "optionId": "Two or More Races (Not Hispanic or Latino)",
259
+ "description": "All persons who identify with more than one of the above five races."
260
+ },
261
+ {
262
+ "text": "Decline to self-identify",
263
+ "optionId": "Decline to self-identify"
264
+ }
265
+ ],
266
+ "prompt": "Race",
267
+ "value": null
268
+ },
269
+ "veteran": {
270
+ "description": "We are a Government contractor subject to the Section 4212 of the Vietnam Era Veterans’ Readjustment Assistance Act of 1974, as amended by the Jobs for Veterans Act of 2002, which requires Government contractors to take affirmative action to employ and advance in employment: (1) Disabled veterans – A veteran who served on active duty in the U.S. military and is entitled to disability compensation (or who but for the receipt of military retired pay would be entitled to disability compensation) under laws administered by the Secretary of Veterans Affairs, or was discharged or released from active duty because of a service-connected disability; (2) Recently separated veteran – A veteran separated during the three-year period beginning on the date of the veteran's discharge or release from active duty in the U.S military, ground, naval, or air service; (3) Active duty wartime or campaign badge veteran – A veteran who served on active duty in the U.S. military during a war, or in a campaign or expedition for which a campaign badge was authorized under the laws administered by the Department of Defense; (4) Armed forces service medal veteran – A veteran who, while serving on active duty in the U.S. military ground, naval, or air service, participated in a United States military operation for which an Armed Forces service medal was awarded pursuant to Executive Order 12985 (61 Fed. Reg. 1209). If you believe that you belong to any of the categories of protected veterans, please indicate by making the appropriate selection.",
271
+ "required": false,
272
+ "text": "Veteran status",
273
+ "type": "dropdown",
274
+ "options": [
275
+ {
276
+ "text": "I am a Protected Veteran",
277
+ "optionId": "I am a Protected Veteran",
278
+ "description": "I identify as one or more of the classifications of protected veteran"
279
+ },
280
+ {
281
+ "text": "I am not a Protected Veteran",
282
+ "optionId": "I am not a Protected Veteran",
283
+ "description": "I do not identify as one or more of the classifications of protected veteran"
284
+ },
285
+ {
286
+ "text": "Decline to self-identify",
287
+ "optionId": "Decline to self-identify",
288
+ "description": "I decline to self-identify for protected veteran status"
289
+ }
290
+ ],
291
+ "prompt": "Veteran status",
292
+ "value": null
293
+ },
294
+ "disability": {
295
+ "description": null,
296
+ "required": false,
297
+ "text": "Voluntary self-identification of disability",
298
+ "type": "dropdown",
299
+ "options": [
300
+ {
301
+ "text": "Yes, I have a disability, or have a history/record of having a disability",
302
+ "optionId": "Yes, I have a disability, or have a history/record of having a disability"
303
+ },
304
+ {
305
+ "text": "No, I don't have a disability, or a history/record of having a disability",
306
+ "optionId": "No, I don't have a disability, or a history/record of having a disability"
307
+ },
308
+ {
309
+ "text": "I don't wish to answer",
310
+ "optionId": "I don't wish to answer"
311
+ }
312
+ ],
313
+ "prompt": "Voluntary self-identification of disability",
314
+ "value": null
315
+ },
316
+ "disabilitySignature": {
317
+ "type": "text",
318
+ "text": "Disability signature",
319
+ "description": "Captured user signature string. eg. \"First Last\"",
320
+ "required": false,
321
+ "value": null
322
+ },
323
+ "disabilitySignatureDate": {
324
+ "type": "text",
325
+ "text": "Disability signature date",
326
+ "description": "Please enter the date when the disabilitySignature was filled out eg. \"11/21/2022\"",
327
+ "required": false,
328
+ "value": null
329
+ }
330
+ }
331
+ }
332
+
333
+ }
@@ -0,0 +1,2 @@
1
+ [ZoneTransfer]
2
+ ZoneId=3
@@ -0,0 +1,52 @@
1
+ {
2
+ "data": {
3
+ "id": "54d15a33-c024-4ba4-bc62-6f9588978758",
4
+ "text": "test",
5
+ "state": "published",
6
+ "distributionChannels": [
7
+ "public"
8
+ ],
9
+ "user": "715f7dbc-7e66-4bf6-949e-2d8bf368f9f5",
10
+ "owner": "715f7dbc-7e66-4bf6-949e-2d8bf368f9f5",
11
+ "hiringManager": null,
12
+ "categories": {
13
+ "commitment": "worktype1",
14
+ "department": null,
15
+ "level": null,
16
+ "location": "STUTTGART",
17
+ "team": "team1",
18
+ "allLocations": [
19
+ "STUTTGART"
20
+ ]
21
+ },
22
+ "tags": [],
23
+ "content": {
24
+ "description": "Hello World\n",
25
+ "descriptionHtml": "<div>Hello World</div>",
26
+ "lists": [],
27
+ "closing": "",
28
+ "closingHtml": ""
29
+ },
30
+ "country": "AS",
31
+ "followers": [
32
+ "715f7dbc-7e66-4bf6-949e-2d8bf368f9f5"
33
+ ],
34
+ "reqCode": "",
35
+ "requisitionCodes": [],
36
+ "urls": {
37
+ "list": "https://jobs.sandbox.lever.co/de",
38
+ "show": "https://jobs.sandbox.lever.co/de/54d15a33-c024-4ba4-bc62-6f9588978758",
39
+ "apply": "https://jobs.sandbox.lever.co/de/54d15a33-c024-4ba4-bc62-6f9588978758/apply"
40
+ },
41
+ "confidentiality": "non-confidential",
42
+ "createdAt": 1716466155252,
43
+ "updatedAt": 1719617791866,
44
+ "workplaceType": "onsite",
45
+ "salaryRange": {
46
+ "min": 1,
47
+ "max": 123,
48
+ "currency": "EUR",
49
+ "interval": "per-year-salary"
50
+ }
51
+ }
52
+ }