Skip to content

Commit 5977cbc

Browse files
authored
Merge pull request #61 from r-spacex/v2-api
API V2 iteration with better filtering support + updated flexible schema
2 parents 5b76088 + 77545dd commit 5977cbc

24 files changed

+908
-63
lines changed

.eslintrc.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@
2323
"error",
2424
2
2525
],
26-
"linebreak-style": [
27-
"error",
28-
"unix"
29-
],
3026
"quotes": [
3127
"error",
3228
"double"

README.md

Lines changed: 50 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -25,65 +25,75 @@ See the [Wiki](https://github.com/r-spacex/SpaceX-API/wiki) for full API Documen
2525
**Example Response**
2626

2727
```http
28-
GET https://api.spacexdata.com/v1/launches/latest
28+
GET https://api.spacexdata.com/v2/launches/latest
2929
```
3030

3131
```json
32-
{
32+
{
3333
"flight_number": 50,
3434
"launch_year": "2017",
35+
"launch_date_unix": 1509392040,
3536
"launch_date_utc": "2017-10-30T19:34:00Z",
3637
"launch_date_local": "2017-10-30T15:34:00-04:00",
3738
"rocket": {
38-
"rocket_id": "falcon9",
39-
"rocket_name": "Falcon 9",
40-
"rocket_type": "FT"
39+
"rocket_id": "falcon9",
40+
"rocket_name": "Falcon 9",
41+
"rocket_type": "FT",
42+
"first_stage": {
43+
"cores": [
44+
{
45+
"core_serial": "B1042",
46+
"reused": false,
47+
"land_success": true,
48+
"landing_type": "ASDS",
49+
"landing_vehicle": "OCISLY"
50+
}
51+
]
52+
},
53+
"second_stage": {
54+
"payloads": [
55+
{
56+
"payload_id": "KoreaSat 5A",
57+
"reused": false,
58+
"customers": [
59+
"KT Corporation"
60+
],
61+
"payload_type": "Satellite",
62+
"payload_mass_kg": 3700,
63+
"payload_mass_lbs": 8157.104,
64+
"orbit": "GTO"
65+
}
66+
]
67+
}
4168
},
4269
"telemetry": {
43-
"flight_club": null
70+
"flight_club": null
4471
},
45-
"core_serial": "B1042",
46-
"cap_serial": null,
4772
"reuse": {
48-
"core": false,
49-
"side_core1": false,
50-
"side_core2": false,
51-
"fairings": false,
52-
"capsule": false
73+
"core": false,
74+
"side_core1": false,
75+
"side_core2": false,
76+
"fairings": false,
77+
"capsule": false
5378
},
5479
"launch_site": {
55-
"site_id": "ksc_lc_39a",
56-
"site_name": "KSC LC 39A"
80+
"site_id": "ksc_lc_39a",
81+
"site_name": "KSC LC 39A",
82+
"site_name_long": "Kennedy Space Center Historic Launch Complex 39A"
5783
},
58-
"payloads": [
59-
{
60-
"payload_id": "KoreaSat 5A",
61-
"customers": [
62-
"KT Corporation"
63-
],
64-
"payload_type": "Satellite",
65-
"payload_mass_kg": 3700,
66-
"payload_mass_lbs": 8157.104,
67-
"orbit": "GTO"
68-
}
69-
],
7084
"launch_success": true,
71-
"reused": false,
72-
"land_success": true,
73-
"landing_type": "ASDS",
74-
"landing_vehicle": "OCISLY",
7585
"links": {
76-
"mission_patch": "http://spacexpatchlist.space/patches/spacex_f9_044_koreasat_5a_graphic.png",
77-
"reddit_campaign": "https://www.reddit.com/r/spacex/comments/73ttkd/koreasat_5a_launch_campaign_thread/",
78-
"reddit_launch": "https://www.reddit.com/r/spacex/comments/79iuvb/rspacex_koreasat_5a_official_launch_discussion/",
79-
"reddit_recovery": null,
80-
"reddit_media": "https://www.reddit.com/r/spacex/comments/79lmdu/rspacex_koreasat5a_media_thread_videos_images/",
81-
"presskit": "http://www.spacex.com/sites/spacex/files/koreasat5apresskit.pdf",
82-
"article_link": "https://spaceflightnow.com/2017/10/30/spacex-launches-and-lands-third-rocket-in-three-weeks/",
83-
"video_link": "https://www.youtube.com/watch?v=RUjH14vhLxA"
86+
"mission_patch": "http://spacexpatchlist.space/patches/spacex_f9_044_koreasat_5a_graphic.png",
87+
"reddit_campaign": "https://www.reddit.com/r/spacex/comments/73ttkd/koreasat_5a_launch_campaign_thread/",
88+
"reddit_launch": "https://www.reddit.com/r/spacex/comments/79iuvb/rspacex_koreasat_5a_official_launch_discussion/",
89+
"reddit_recovery": null,
90+
"reddit_media": "https://www.reddit.com/r/spacex/comments/79lmdu/rspacex_koreasat5a_media_thread_videos_images/",
91+
"presskit": "http://www.spacex.com/sites/spacex/files/koreasat5apresskit.pdf",
92+
"article_link": "https://spaceflightnow.com/2017/10/30/spacex-launches-and-lands-third-rocket-in-three-weeks/",
93+
"video_link": "https://www.youtube.com/watch?v=RUjH14vhLxA"
8494
},
8595
"details": "KoreaSat 5A is a Ku-band satellite capable of providing communication services from East Africa and Central Asia to southern India, Southeast Asia, the Philippines, Guam, Korea, and Japan. The satellite will be placed in GEO at 113° East Longitude, and will provide services ranging from broadband internet to broadcasting services and maritime communications."
86-
}
96+
}
8797
```
8898

8999
## Contributions

app.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,21 @@ const config = require("./config.json")
88
const MongoClient = require("mongodb")
99
const app = express()
1010

11-
const home = require("./routes/v1-home")
12-
const info = require("./routes/v1-info")
13-
const vehicles = require("./routes/v1-vehicles")
14-
const launchpad = require("./routes/v1-launchpad")
15-
const launches = require("./routes/v1-launches")
16-
const upcoming = require("./routes/v1-upcoming")
17-
const parts = require("./routes/v1-parts")
11+
const home = require("./v1-routes/v1-home")
12+
const info = require("./v1-routes/v1-info")
13+
const vehicles = require("./v1-routes/v1-vehicles")
14+
const launchpad = require("./v1-routes/v1-launchpad")
15+
const launches = require("./v1-routes/v1-launches")
16+
const upcoming = require("./v1-routes/v1-upcoming")
17+
const parts = require("./v1-routes/v1-parts")
18+
19+
const v2_home = require("./v2-routes/v2-home")
20+
const v2_info = require("./v2-routes/v2-info")
21+
const v2_vehicles = require("./v2-routes/v2-vehicles")
22+
const v2_launchpad = require("./v2-routes/v2-launchpad")
23+
const v2_launches = require("./v2-routes/v2-launches")
24+
const v2_upcoming = require("./v2-routes/v2-upcoming")
25+
const v2_parts = require("./v2-routes/v2-parts")
1826

1927
app.use(compression())
2028
app.use(helmet())
@@ -36,6 +44,14 @@ app.use("/v1/launches", launches)
3644
app.use("/v1/launches/upcoming", upcoming)
3745
app.use("/v1/parts", parts)
3846

47+
app.use("/v2", v2_home)
48+
app.use("/v2/info", v2_info)
49+
app.use("/v2/vehicles", v2_vehicles)
50+
app.use("/v2/launchpads", v2_launchpad)
51+
app.use("/v2/launches", v2_launches)
52+
app.use("/v2/launches/upcoming", v2_upcoming)
53+
app.use("/v2/parts", v2_parts)
54+
3955
// 404 Error Handler
4056
app.use((req, res) => {
4157
res.status(404)

builders/capsule-query.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Returns capsule query object from optional querystring inputs
3+
*/
4+
5+
exports.capsuleQuery = (req) => {
6+
let query = {}
7+
8+
if (req.query.capsule_serial) {
9+
query.capsule_serial = req.query.capsule_serial
10+
}
11+
if (req.query.status) {
12+
query.status = req.query.status
13+
}
14+
if (req.query.original_launch) {
15+
query.original_launch = req.query.original_launch
16+
}
17+
if (req.query.missions) {
18+
query.missions = req.query.missions
19+
}
20+
if (req.query.landings) {
21+
query.landings = parseInt(req.query.landings)
22+
}
23+
if (req.query.type) {
24+
query.type = req.query.type
25+
}
26+
return query
27+
}

builders/core-query.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* Returns core query object from optional querystring inputs
3+
*/
4+
5+
exports.coreQuery = (req) => {
6+
let query = {}
7+
8+
if (req.query.core_serial) {
9+
query.core_serial = req.query.core_serial
10+
}
11+
if (req.query.status) {
12+
query.status = req.query.status
13+
}
14+
if (req.query.original_launch) {
15+
query.original_launch = req.query.original_launch
16+
}
17+
if (req.query.missions) {
18+
query.missions = req.query.missions
19+
}
20+
if (req.query.rtls_attempt) {
21+
query.rtls_attempt = Boolean(req.query.rtls_attempt)
22+
}
23+
if (req.query.rtls_landings) {
24+
query.rtls_landings = parseInt(req.query.rtls_landings)
25+
}
26+
if (req.query.asds_attempt) {
27+
query.asds_attempt = Boolean(req.query.asds_attempt)
28+
}
29+
if (req.query.asds_landings) {
30+
query.asds_landings = parseInt(req.query.asds_landings)
31+
}
32+
if (req.query.water_landing) {
33+
query.water_landing = Boolean(req.query.water_landing)
34+
}
35+
return query
36+
}

builders/launch-query.js

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/**
2+
* Returns launch query object from optional querystring inputs
3+
*/
4+
5+
exports.launchQuery = (req) => {
6+
let query = {}
7+
8+
if (req.query.start && req.query.final) {
9+
query.launch_date_utc = {"$gte": `${req.query.start}T00:00:00Z`, "$lte": `${req.query.final}T00:00:00Z`}
10+
}
11+
if (req.query.flight_number) {
12+
query.flight_number = parseInt(req.query.flight_number)
13+
}
14+
if (req.query.launch_year) {
15+
query.launch_year = req.query.launch_year
16+
}
17+
if (req.query.launch_date_utc) {
18+
query.launch_date_utc = req.query.launch_date_utc
19+
}
20+
if (req.query.launch_date_local) {
21+
query.launch_date_local = req.query.launch_date_local
22+
}
23+
if (req.query.rocket_id) {
24+
query["rocket.rocket_id"] = req.query.rocket_id
25+
}
26+
if (req.query.rocket_name) {
27+
query["rocket.rocket_name"] = req.query.rocket_name
28+
}
29+
if (req.query.rocket_type) {
30+
query["rocket.rocket_type"] = req.query.rocket_type
31+
}
32+
if (req.query.core_serial) {
33+
query["rocket.first_stage.cores.core_serial"] = req.query.core_serial
34+
}
35+
if (req.query.cap_serial) {
36+
query["rocket.second_stage.payloads.cap_serial"] = req.query.cap_serial
37+
}
38+
if (req.query.core_reuse) {
39+
query["reuse.core"] = Boolean(req.query.core_reuse)
40+
}
41+
if (req.query.side_core1_reuse) {
42+
query["reuse.side_core1"] = Boolean(req.query.side_core1_reuse)
43+
}
44+
if (req.query.side_core2_reuse) {
45+
query["reuse.side_core2"] = Boolean(req.query.side_core2_reuse)
46+
}
47+
if (req.query.fairings_reuse) {
48+
query["reuse.fairings"] = Boolean(req.query.fairings_reuse)
49+
}
50+
if (req.query.capsule_reuse) {
51+
query["reuse.capsule"] = Boolean(req.query.capsule_reuse)
52+
}
53+
if (req.query.site_id) {
54+
query["launch_site.site_id"] = req.query.site_id
55+
}
56+
if (req.query.site_name) {
57+
query["launch_site.site_name"] = req.query.site_name
58+
}
59+
if (req.query.payload_id) {
60+
query["rocket.second_stage.payloads.payload_id"] = req.query.payload_id
61+
}
62+
if (req.query.customer) {
63+
query["rocket.second_stage.payloads.customers"] = req.query.customer
64+
}
65+
if (req.query.payload_type) {
66+
query["rocket.second_stage.payloads.payload_type"] = req.query.payload_type
67+
}
68+
if (req.query.orbit) {
69+
query["rocket.second_stage.payloads.orbit"] = req.query.orbit
70+
}
71+
if (req.query.launch_success) {
72+
query.launch_success = Boolean(req.query.launch_success)
73+
}
74+
if (req.query.reused) {
75+
query["rocket.first_stage.cores.reused"] = Boolean(req.query.reused)
76+
}
77+
if (req.query.land_success) {
78+
query["rocket.first_stage.cores.land_success"] = Boolean(req.query.land_success)
79+
}
80+
if (req.query.landing_type) {
81+
query["rocket.first_stage.cores.landing_type"] = req.query.landing_type
82+
}
83+
if (req.query.landing_vehicle) {
84+
query["rocket.first_stage.cores.landing_vehicle"] = req.query.landing_vehicle
85+
}
86+
return query
87+
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{
2-
"name": "spacex-api-node",
3-
"version": "1.0.0",
4-
"description": "Repo for staging/testing SpaceX-API transition from Ruby to Javascript (Node.js)",
5-
"main": "server.js",
2+
"name": "spacex-api",
3+
"version": "2.0.2",
4+
"description": "Open Source REST API for SpaceX company, vehicle, launchpad, and launch data",
5+
"main": "app.js",
66
"scripts": {
7-
"test": "jest --forceExit && codecov && eslint \"**/*.js\"",
7+
"test": "PORT=0 jest -i --forceExit && codecov && eslint \"**/*.js\"",
88
"start": "node app.js",
99
"lint": "eslint \"**/*.js\""
1010
},
1111
"repository": {
1212
"type": "git",
13-
"url": "git+https://github.com/jakewmeyer/SpaceX-API-Node.git"
13+
"url": "git+https://github.com/r-spacex/SpaceX-API"
1414
},
1515
"keywords": [
1616
"spacex",
@@ -21,9 +21,9 @@
2121
"author": "Jake Meyer",
2222
"license": "MIT",
2323
"bugs": {
24-
"url": "https://github.com/jakewmeyer/SpaceX-API-Node/issues"
24+
"url": "https://github.com/r-spacex/SpaceX-API/issues"
2525
},
26-
"homepage": "https://github.com/jakewmeyer/SpaceX-API-Node#readme",
26+
"homepage": "https://github.com/r-spacex/SpaceX-API",
2727
"dependencies": {
2828
"apicache": "^1.1.0",
2929
"codecov": "^2.3.0",

test/v1-all.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11

2-
const app = require("../app")
32
const request = require("supertest")
3+
const app = require("../app")
44
const customMatchers = require("./utilities/custom-asymmetric-matchers")
55

66
beforeAll((done) => {
@@ -14,7 +14,7 @@ beforeAll((done) => {
1414
//------------------------------------------------------------
1515

1616
test("It should return 404 endpoint error", () => {
17-
return request(app).get("/v2").then(response => {
17+
return request(app).get("/v3").then(response => {
1818
expect(response.statusCode).toBe(404)
1919
expect(response.body).toMatchObject({
2020
error: "No results found"

0 commit comments

Comments
 (0)