Skip to content

Commit a0f9289

Browse files
committed
should not enforce yaml for config files, should also allow json - fixes #25
1 parent d97858b commit a0f9289

File tree

9 files changed

+176
-14
lines changed

9 files changed

+176
-14
lines changed

src/lib/from_file.rs

+70-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use std::path::PathBuf;
99

1010
#[derive(Debug)]
1111
pub enum FromFileError {
12+
InvalidExtension,
1213
InvalidInput,
1314
FileOpen(PathBuf),
1415
FileRead,
@@ -23,6 +24,41 @@ pub enum FromFileError {
2324
/// - file:conf/app.yaml
2425
///
2526
pub trait FromFile {
27+
///
28+
/// Support serialising to .yml, .yaml & .json files by
29+
/// looking at the file extension and then choosing the correct
30+
/// serde method
31+
///
32+
/// # Examples
33+
///
34+
/// ```ignore
35+
/// #[derive(Deserialize, Debug, PartialEq)]
36+
/// struct Person {
37+
/// name: String
38+
/// }
39+
///
40+
/// impl FromFile for Person {}
41+
///
42+
/// let p1 = Person::from_file("test/fixtures/person.json").expect("file->Person");
43+
/// assert_eq!(p1, Person{name: "Shane".into()});
44+
/// ```
45+
///
46+
fn from_file(input: &str) -> Result<Self, FromFileError>
47+
where
48+
for<'de> Self: Deserialize<'de> + Sized,
49+
{
50+
let pb = PathBuf::from(input);
51+
let ext = pb
52+
.extension()
53+
.and_then(|ext| ext.to_str())
54+
.ok_or(FromFileError::InvalidExtension)?;
55+
match ext {
56+
"json" => <Self as FromFile>::from_json_file(input),
57+
"yml" | "yaml" => <Self as FromFile>::from_yml_file(input),
58+
_ => Err(FromFileError::InvalidExtension),
59+
}
60+
}
61+
2662
///
2763
/// From a string like `file:config.yaml`, try to read the file
2864
/// and if it exists, parse into a strongly typed struct `Person`
@@ -98,12 +134,42 @@ pub trait FromFile {
98134
impl std::fmt::Display for FromFileError {
99135
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
100136
match self {
101-
FromFileError::InvalidInput => write!(f, "ConfigError::InvalidInput"),
137+
FromFileError::InvalidExtension => write!(f, "FromFileError::InvalidExtension"),
138+
FromFileError::InvalidInput => write!(f, "FromFileError::InvalidInput"),
102139
FromFileError::FileOpen(path) => {
103-
write!(f, "ConfigError::FileOpen - couldn't open {:?}", path)
140+
write!(f, "FromFileError::FileOpen - couldn't open {:?}", path)
104141
}
105-
FromFileError::FileRead => write!(f, "ConfigError::FileRead"),
106-
FromFileError::SerdeError(e) => write!(f, "ConfigError::SerdeError - {}", e),
142+
FromFileError::FileRead => write!(f, "FromFileError::FileRead"),
143+
FromFileError::SerdeError(e) => write!(f, "FromFileError::SerdeError - {}", e),
144+
}
145+
}
146+
}
147+
148+
#[cfg(test)]
149+
mod tests {
150+
use from_file::FromFile;
151+
#[test]
152+
fn test_from_file() {
153+
#[derive(Deserialize, Debug, PartialEq)]
154+
struct Person {
155+
name: String,
107156
}
157+
impl FromFile for Person {}
158+
159+
let p1 = Person::from_file("test/fixtures/person.json").expect("file->Person");
160+
assert_eq!(
161+
p1,
162+
Person {
163+
name: "Shane".into()
164+
}
165+
);
166+
167+
let p1 = Person::from_file("test/fixtures/person.yaml").expect("file->Person");
168+
assert_eq!(
169+
p1,
170+
Person {
171+
name: "Shane".into()
172+
}
173+
);
108174
}
109175
}

src/lib/presets/m2/state.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub fn gather_state(
2828
let bundle_path = maybe_opts.bundle_config;
2929

3030
match bundle_path {
31-
Some(bun_config_path) => match BundleConfig::from_yml_file(&bun_config_path) {
31+
Some(bun_config_path) => match BundleConfig::from_file(&bun_config_path) {
3232
Ok(bundle_config) => {
3333
let module_blacklist = bundle_config.module_blacklist.clone().unwrap_or(vec![]);
3434
let mut blacklist = vec!["js-translation".to_string()];

src/lib/setup.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ pub fn create_state(
8787
opts: ProgramOptions,
8888
) -> AppState {
8989
let (req_log, rjs_client_config) = match maybe_seed {
90-
Some(ref s) => match SeedData::from_json_file(&s) {
90+
Some(ref s) => match SeedData::from_file(&s) {
9191
Ok(seed) => (seed.req_log, seed.rjs_client_config),
9292
Err(e) => {
9393
eprintln!("Could not read seed, {:?}", e);

src/lib/system.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub fn create(opts: ProgramOptions) -> Result<(actix::SystemRunner, String), Pro
1818

1919
//
2020
// Get program configuration, from the input above, and
21-
// then eventuall from a file
21+
// then eventually from a file
2222
//
2323
let file_path = opts
2424
.config_file
@@ -29,7 +29,7 @@ pub fn create(opts: ProgramOptions) -> Result<(actix::SystemRunner, String), Pro
2929
// Pull the ProgramConfig from a file
3030
//
3131
let program_config =
32-
ProgramConfig::from_yml_file(&file_path).map_err(|e| ProgramStartError::FromFile(e))?;
32+
ProgramConfig::from_file(&file_path).map_err(|e| ProgramStartError::FromFile(e))?;
3333

3434
//
3535
// Clone server opts to be used in multi threads

test/fixtures/bundle-config.json

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
{
2+
"bundles": [
3+
{
4+
"name": "bundles/main",
5+
"urls": [
6+
"/",
7+
"/index.php/women/tops-women/jackets-women.html"
8+
],
9+
"children": [
10+
{
11+
"name": "bundles/product",
12+
"urls": [
13+
"/index.php/juno-jacket.html"
14+
],
15+
"children": [
16+
17+
]
18+
},
19+
{
20+
"name": "bundles/basket",
21+
"urls": [
22+
"/index.php/checkout/cart/",
23+
"/index.php/checkout/cart"
24+
],
25+
"children": [
26+
{
27+
"name": "bundles/checkout",
28+
"urls": [
29+
"/index.php/checkout/"
30+
],
31+
"children": [
32+
33+
]
34+
}
35+
]
36+
}
37+
]
38+
}
39+
]
40+
}

test/fixtures/config.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"presets": [
3+
{
4+
"name": "m2",
5+
"options": {
6+
"bundle_config": "file:test/fixtures/bundle-config.json",
7+
"auth_basic": {
8+
"username": "acme",
9+
"password": "acmepw"
10+
}
11+
}
12+
}
13+
]
14+
}

test/fixtures/person.json

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"name": "Shane"
3+
}

test/fixtures/person.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
name: "Shane"

tests/api.rs

+44-6
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use actix_web::http;
1010
use bs::config::ProgramStartError;
1111
use bs::options::ProgramOptions;
1212
use bs::presets::m2::requirejs_config::{RequireJsBuildConfig, RequireJsClientConfig};
13+
use bs::presets::m2::seed::SeedData;
1314
use bs::system;
1415
use reqwest::Response;
1516

@@ -31,9 +32,9 @@ const DEFAULT_ARGS: &'static [&'static str] = &[
3132
fn test_config_json() {
3233
api(DEFAULT_ARGS.to_vec(), "/__bs/config.json", |result| {
3334
let (_sys, _url, mut res) = result.expect("api returned");
34-
let _c: RequireJsClientConfig =
35-
serde_json::from_str(&res.text().expect("unwrap text response"))
36-
.expect("serde deserialize");
35+
let _c: RequireJsClientConfig = serde_json::from_str(
36+
&res.text().expect("unwrap text response"),
37+
).expect("serde deserialize");
3738
});
3839
}
3940

@@ -49,13 +50,50 @@ fn test_loaders_js() {
4950
});
5051
}
5152

53+
#[test]
54+
fn test_seed_json() {
55+
api(DEFAULT_ARGS.to_vec(), "/__bs/seed.json", |result| {
56+
let (_sys, _url, mut res) = result.expect("api returned");
57+
let t = res.text().expect("unwrap text response");
58+
let _c: SeedData = serde_json::from_str(&t).expect("serde deserialize");
59+
});
60+
}
61+
62+
#[test]
63+
fn test_seed_seeded_json() {
64+
let mut args = DEFAULT_ARGS.to_vec().clone();
65+
args.extend(vec!["--seed", "test/fixtures/seed.json"]);
66+
api(args, "/__bs/seed.json", |result| {
67+
let (_sys, _url, mut res) = result.expect("api returned");
68+
let t = res.text().expect("unwrap text response");
69+
let c: SeedData = serde_json::from_str(&t).expect("serde deserialize");
70+
assert_eq!(c.req_log.len(), 339);
71+
});
72+
}
73+
5274
#[test]
5375
fn test_build_json() {
5476
api(DEFAULT_ARGS.to_vec(), "/__bs/build.json", |result| {
5577
let (_sys, _url, mut res) = result.expect("api returned");
56-
let _c: RequireJsBuildConfig =
57-
serde_json::from_str(&res.text().expect("unwrap text response"))
58-
.expect("serde deserialize");
78+
let _c: RequireJsBuildConfig = serde_json::from_str(
79+
&res.text().expect("unwrap text response"),
80+
).expect("serde deserialize");
81+
});
82+
}
83+
84+
#[test]
85+
fn test_build_json_from_json_config() {
86+
let args = vec![
87+
"config-gen",
88+
"http://example.com",
89+
"--config",
90+
"test/fixtures/config.json",
91+
];
92+
api(args, "/__bs/build.json", |result| {
93+
let (_sys, _url, mut res) = result.expect("api returned");
94+
let _c: RequireJsBuildConfig = serde_json::from_str(
95+
&res.text().expect("unwrap text response"),
96+
).expect("serde deserialize");
5997
});
6098
}
6199

0 commit comments

Comments
 (0)