├── .editorconfig ├── .gitignore ├── LICENSE ├── README.md ├── angular.json ├── apollo.config.js ├── browserslist ├── codegen.yml ├── details-example.jpg ├── e2e ├── protractor.conf.js ├── src │ ├── app.e2e-spec.ts │ └── app.po.ts └── tsconfig.json ├── karma.conf.js ├── list-example.jpg ├── package-lock.json ├── package.json ├── src ├── app │ ├── app-routing.module.ts │ ├── app.component.css │ ├── app.component.html │ ├── app.component.spec.ts │ ├── app.component.ts │ ├── app.module.ts │ ├── graphql.module.ts │ ├── launch-details │ │ ├── launch-details.component.css │ │ ├── launch-details.component.html │ │ ├── launch-details.component.spec.ts │ │ ├── launch-details.component.ts │ │ └── launch-details.graphql │ ├── launch-list │ │ ├── launch-list.component.css │ │ ├── launch-list.component.html │ │ ├── launch-list.component.spec.ts │ │ ├── launch-list.component.ts │ │ └── launch-list.graphql │ ├── relative-time │ │ ├── relative-time.pipe.spec.ts │ │ └── relative-time.pipe.ts │ └── services │ │ └── spacexGraphql.service.ts ├── assets │ └── .gitkeep ├── environments │ ├── environment.prod.ts │ └── environment.ts ├── favicon.ico ├── index.html ├── main.ts ├── polyfills.ts ├── styles.css └── test.ts ├── tsconfig.app.json ├── tsconfig.json ├── tsconfig.spec.json └── tslint.json /.editorconfig: -------------------------------------------------------------------------------- 1 | # Editor configuration, see https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | 11 | [*.md] 12 | max_line_length = off 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See http://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # compiled output 4 | /dist 5 | /tmp 6 | /out-tsc 7 | # Only exists if Bazel was run 8 | /bazel-out 9 | 10 | # dependencies 11 | /node_modules 12 | 13 | # profiling files 14 | chrome-profiler-events*.json 15 | speed-measure-plugin*.json 16 | 17 | # IDEs and editors 18 | /.idea 19 | .project 20 | .classpath 21 | .c9/ 22 | *.launch 23 | .settings/ 24 | *.sublime-workspace 25 | 26 | # IDE - VSCode 27 | .vscode/* 28 | !.vscode/settings.json 29 | !.vscode/tasks.json 30 | !.vscode/launch.json 31 | !.vscode/extensions.json 32 | .history/* 33 | 34 | # misc 35 | /.sass-cache 36 | /connect.lock 37 | /coverage 38 | /libpeerconnection.log 39 | npm-debug.log 40 | yarn-error.log 41 | testem.log 42 | /typings 43 | 44 | # System Files 45 | .DS_Store 46 | Thumbs.db 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | 24 | For more information, please refer to 25 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Angular Spacex Graphql Codegen 2 | 3 | ## Mission 4 | 5 | Our goal is to make an Angular app with a list of the past SpaceX launches along with an associated details page. Data is provided via the [SpaceX GraphQL API](https://medium.com/open-graphql/launching-spacex-graphql-api-b3d7029086e0) and Angular services are generated via [GraphQL Code Generator](https://graphql-code-generator.com/). We use [Apollo Angular](https://www.apollographql.com/docs/angular/) to access data from the frontend. The API is free so please be nice and don't abuse it. 6 | 7 | ## End Result 8 | 9 | ![List view](list-example.jpg) 10 | 11 | ![Details view](details-example.jpg) 12 | 13 | ## Steps 14 | 15 | 1. Generate a new angular application with routing 16 | 17 | ```bash 18 | ng new angular-spacex-graphql-codegen --routing=true --style=css 19 | ``` 20 | 21 | Make sure to delete the default template in `src/app/app.component.html` 22 | 23 | 1. Install the [Apollo VS Code plugin](https://marketplace.visualstudio.com/items?itemName=apollographql.vscode-apollo) and in the root of the project add `apollo.config.js` 24 | 25 | ```javascript 26 | module.exports = { 27 | client: { 28 | service: { 29 | name: 'angular-spacex-graphql-codegen', 30 | url: 'https://api.spacex.land/graphql/' 31 | } 32 | } 33 | }; 34 | ``` 35 | 36 | This points the extension at the SpaceX GraphQL API so we get autocomplete, type information, and other cool features in GraphQL files. You may need to restart VS Code. 37 | 38 | 1. Generate our two components: 39 | 40 | ```bash 41 | ng g component launch-list --changeDetection=OnPush 42 | ``` 43 | 44 | ```bash 45 | ng g component launch-details --changeDetection=OnPush 46 | ``` 47 | 48 | Because our generated services use observables we choose OnPush change detection for the best performance. 49 | 50 | 1. In `src/app/app-routing.module.ts` we setup the routing: 51 | 52 | ```typescript 53 | import { LaunchListComponent } from './launch-list/launch-list.component'; 54 | import { LaunchDetailsComponent } from './launch-details/launch-details.component'; 55 | 56 | const routes: Routes = [ 57 | { 58 | path: '', 59 | component: LaunchListComponent 60 | }, 61 | { 62 | path: ':id', 63 | component: LaunchDetailsComponent 64 | } 65 | ]; 66 | ``` 67 | 68 | 1. Each component will have its own data requirments so we co-locate our graphql query files next to them 69 | 70 | ```graphql 71 | # src/app/launch-list/launch-list.graphql 72 | 73 | query pastLaunchesList($limit: Int!) { 74 | launchesPast(limit: $limit) { 75 | id 76 | mission_name 77 | links { 78 | flickr_images 79 | mission_patch_small 80 | } 81 | rocket { 82 | rocket_name 83 | } 84 | launch_date_utc 85 | } 86 | } 87 | ``` 88 | 89 | ```graphql 90 | # src/app/launch-details/launch-details.graphql 91 | 92 | query launchDetails($id: ID!) { 93 | launch(id: $id) { 94 | id 95 | mission_name 96 | details 97 | links { 98 | flickr_images 99 | mission_patch 100 | } 101 | } 102 | } 103 | ``` 104 | 105 | Note the first line: `query launchDetails($id: ID!)` When we generate the Angular service the query name is turned into PascalCase and GQL is appended to the end, so the service name for the launch details would be LaunchDetailsGQL. Also in the first line we define any variables we'll need to pass into the query. Please note it's import to include id in the query return so apollo can cache the data. 106 | 107 | 1. We add [Apollo Angular](https://www.apollographql.com/docs/angular/) to our app with `ng add apollo-angular`. In `src/app/graphql.module.ts` we set our API url `const uri = 'https://api.spacex.land/graphql/';`. 108 | 109 | 1. Install Graphql Code Generator and the needed plugins `npm i --save-dev @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-apollo-angular @graphql-codegen/typescript-operations` 110 | 111 | 1. In the root of the project create a `codegen.yml` file: 112 | 113 | ```yml 114 | # Where to get schema data 115 | schema: 116 | - https://api.spacex.land/graphql/ 117 | # The client side queries to turn into services 118 | documents: 119 | - src/**/*.graphql 120 | # Where to output the services and the list of plugins 121 | generates: 122 | ./src/app/services/spacexGraphql.service.ts: 123 | plugins: 124 | - typescript 125 | - typescript-operations 126 | - typescript-apollo-angular 127 | ``` 128 | 129 | 1. In package.json add a script `"codegen": "gql-gen"` then `npm run codegen` to generate the Angular Services. 130 | 131 | 1. To make it look nice we add Angular Material `ng add @angular/material` then in the `app.module.ts` we import the card module and add to the imports array: `import { MatCardModule } from '@angular/material/card';` 132 | 133 | 1. Lets start with the list of past launches displayed on the screen: 134 | 135 | ```typescript 136 | import { map } from 'rxjs/operators'; 137 | import { PastLaunchesListGQL } from '../services/spacexGraphql.service'; 138 | 139 | export class LaunchListComponent { 140 | constructor(private readonly pastLaunchesService: PastLaunchesListGQL) {} 141 | 142 | // Please be careful to not fetch too much, but this amount lets us see lazy loading imgs in action 143 | pastLaunches$ = this.pastLaunchesService 144 | .fetch({ limit: 30 }) 145 | // Here we extract our query data, we can also get info like errors or loading state from res 146 | .pipe(map((res) => res.data.launchesPast)); 147 | } 148 | ``` 149 | 150 | ```html 151 | 152 |
153 |
154 | 158 | 159 | Mission patch of {{ launch.mission_name }} 167 | {{ launch.mission_name }} 168 | {{ launch.rocket.rocket_name }} 171 | 172 | Photo of {{ launch.mission_name }} 180 | 181 |
182 |
183 |
184 | ``` 185 | 186 | Notice the cool addition of [lazy loading images](https://web.dev/native-lazy-loading), if you emulate a mobile device in Chrome and fetch enough launches you should see the images lazy load while you scroll! 187 | 188 | To make it look nice we add CSS Grid 189 | 190 | ```css 191 | .container { 192 | padding-top: 20px; 193 | display: grid; 194 | grid-gap: 30px; 195 | grid-template-columns: repeat(auto-fill, 350px); 196 | justify-content: center; 197 | } 198 | 199 | .mat-card { 200 | cursor: pointer; 201 | } 202 | ``` 203 | 204 | 1. Next we make the details page for a launch, we get the id from the route params and pass that to our service 205 | 206 | ```typescript 207 | import { ActivatedRoute } from '@angular/router'; 208 | import { map, switchMap } from 'rxjs/operators'; 209 | import { LaunchDetailsGQL } from '../services/spacexGraphql.service'; 210 | 211 | export class LaunchDetailsComponent { 212 | constructor( 213 | private readonly route: ActivatedRoute, 214 | private readonly launchDetailsService: LaunchDetailsGQL 215 | ) {} 216 | 217 | launchDetails$ = this.route.paramMap.pipe( 218 | map((params) => params.get('id') as string), 219 | switchMap((id) => this.launchDetailsService.fetch({ id })), 220 | map((res) => res.data.launch) 221 | ); 222 | } 223 | ``` 224 | 225 | The HTML looks very similar to the list of launches 226 | 227 | ```html 228 | 229 |
230 | 231 | 232 | {{ launchDetails.mission_name }} 233 | 234 | Mission patch of {{ launchDetails.mission_name }} 241 | 242 |

{{ launchDetails.details }}

243 |
244 |
245 |
246 |
247 | Picture of {{ launchDetails.mission_name }} 255 |
256 |
257 | ``` 258 | 259 | Finally we add CSS Grid for the pictures 260 | 261 | ```css 262 | .photo-grid { 263 | padding-top: 30px; 264 | display: grid; 265 | grid-gap: 10px; 266 | grid-template-columns: repeat(auto-fill, 300px); 267 | justify-content: center; 268 | } 269 | ``` 270 | 271 | 1. `npm start`, navigate to `http://localhost:4200/`, and it should work! 272 | 273 | ### Extra Credit: Relative launch times 274 | 275 | Thanks to the new builtin [relative time formating](https://v8.dev/features/intl-relativetimeformat) in V8, we can add `launched x days ago` 276 | 277 | 1. Generate the pipe: `ng g pipe relative-time --module=app.module --flat=false` 278 | 279 | 1. The pipe takes in the UTC time and returns a formatted string 280 | 281 | ```typescript 282 | import { Pipe, PipeTransform } from '@angular/core'; 283 | 284 | const milliSecondsInDay = 1000 * 3600 * 24; 285 | 286 | // Cast as any because typescript typing haven't updated yet 287 | const rtf = new (Intl as any).RelativeTimeFormat('en'); 288 | 289 | @Pipe({ 290 | name: 'relativeTime' 291 | }) 292 | export class RelativeTimePipe implements PipeTransform { 293 | transform(utcTime: string): string { 294 | const diffInMillicseconds = 295 | new Date(utcTime).getTime() - new Date().getTime(); 296 | const diffInDays = Math.round(diffInMillicseconds / milliSecondsInDay); 297 | return rtf.format(diffInDays, 'day'); 298 | } 299 | } 300 | ``` 301 | 302 | 1. Add the pipe to our launch card in src/app/launch-list/launch-list.component.html 303 | 304 | ```html 305 | {{ launch.rocket.rocket_name }} - launched {{ launch.launch_date_utc | 307 | relativeTime }} 309 | ``` 310 | -------------------------------------------------------------------------------- /angular.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", 3 | "version": 1, 4 | "newProjectRoot": "projects", 5 | "projects": { 6 | "angular-spacex-graphql-codegen": { 7 | "projectType": "application", 8 | "schematics": {}, 9 | "root": "", 10 | "sourceRoot": "src", 11 | "prefix": "app", 12 | "architect": { 13 | "build": { 14 | "builder": "@angular-devkit/build-angular:browser", 15 | "options": { 16 | "outputPath": "dist/angular-spacex-graphql-codegen", 17 | "index": "src/index.html", 18 | "main": "src/main.ts", 19 | "polyfills": "src/polyfills.ts", 20 | "tsConfig": "tsconfig.app.json", 21 | "aot": false, 22 | "assets": [ 23 | "src/favicon.ico", 24 | "src/assets" 25 | ], 26 | "styles": [ 27 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 28 | "src/styles.css" 29 | ], 30 | "scripts": [] 31 | }, 32 | "configurations": { 33 | "production": { 34 | "fileReplacements": [ 35 | { 36 | "replace": "src/environments/environment.ts", 37 | "with": "src/environments/environment.prod.ts" 38 | } 39 | ], 40 | "optimization": true, 41 | "outputHashing": "all", 42 | "sourceMap": false, 43 | "extractCss": true, 44 | "namedChunks": false, 45 | "aot": true, 46 | "extractLicenses": true, 47 | "vendorChunk": false, 48 | "buildOptimizer": true, 49 | "budgets": [ 50 | { 51 | "type": "initial", 52 | "maximumWarning": "2mb", 53 | "maximumError": "5mb" 54 | }, 55 | { 56 | "type": "anyComponentStyle", 57 | "maximumWarning": "6kb", 58 | "maximumError": "10kb" 59 | } 60 | ] 61 | } 62 | } 63 | }, 64 | "serve": { 65 | "builder": "@angular-devkit/build-angular:dev-server", 66 | "options": { 67 | "browserTarget": "angular-spacex-graphql-codegen:build" 68 | }, 69 | "configurations": { 70 | "production": { 71 | "browserTarget": "angular-spacex-graphql-codegen:build:production" 72 | } 73 | } 74 | }, 75 | "extract-i18n": { 76 | "builder": "@angular-devkit/build-angular:extract-i18n", 77 | "options": { 78 | "browserTarget": "angular-spacex-graphql-codegen:build" 79 | } 80 | }, 81 | "test": { 82 | "builder": "@angular-devkit/build-angular:karma", 83 | "options": { 84 | "main": "src/test.ts", 85 | "polyfills": "src/polyfills.ts", 86 | "tsConfig": "tsconfig.spec.json", 87 | "karmaConfig": "karma.conf.js", 88 | "assets": [ 89 | "src/favicon.ico", 90 | "src/assets" 91 | ], 92 | "styles": [ 93 | "./node_modules/@angular/material/prebuilt-themes/indigo-pink.css", 94 | "src/styles.css" 95 | ], 96 | "scripts": [] 97 | } 98 | }, 99 | "lint": { 100 | "builder": "@angular-devkit/build-angular:tslint", 101 | "options": { 102 | "tsConfig": [ 103 | "tsconfig.app.json", 104 | "tsconfig.spec.json", 105 | "e2e/tsconfig.json" 106 | ], 107 | "exclude": [ 108 | "**/node_modules/**" 109 | ] 110 | } 111 | }, 112 | "e2e": { 113 | "builder": "@angular-devkit/build-angular:protractor", 114 | "options": { 115 | "protractorConfig": "e2e/protractor.conf.js", 116 | "devServerTarget": "angular-spacex-graphql-codegen:serve" 117 | }, 118 | "configurations": { 119 | "production": { 120 | "devServerTarget": "angular-spacex-graphql-codegen:serve:production" 121 | } 122 | } 123 | } 124 | } 125 | } 126 | }, 127 | "defaultProject": "angular-spacex-graphql-codegen" 128 | } -------------------------------------------------------------------------------- /apollo.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | client: { 3 | service: { 4 | name: 'angular-spacex-graphql-codegen', 5 | url: 'https://api.spacex.land/graphql/' 6 | } 7 | } 8 | }; 9 | -------------------------------------------------------------------------------- /browserslist: -------------------------------------------------------------------------------- 1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below. 2 | # For additional information regarding the format and rule options, please see: 3 | # https://github.com/browserslist/browserslist#queries 4 | 5 | # You can see what browsers were selected by your queries by running: 6 | # npx browserslist 7 | 8 | > 0.5% 9 | last 2 versions 10 | Firefox ESR 11 | not dead 12 | not IE 9-11 # For IE 9-11 support, remove 'not'. -------------------------------------------------------------------------------- /codegen.yml: -------------------------------------------------------------------------------- 1 | # Where to get schema data 2 | schema: 3 | - https://api.spacex.land/graphql/ 4 | # The client side queries to turn into services 5 | documents: 6 | - src/**/*.graphql 7 | # Where to output the services and the list of plugins 8 | generates: 9 | ./src/app/services/spacexGraphql.service.ts: 10 | plugins: 11 | - typescript 12 | - typescript-operations 13 | - typescript-apollo-angular 14 | -------------------------------------------------------------------------------- /details-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjunyel/angular-spacex-graphql-codegen/6b7bfaf0138f3558d066ea83582b399c777fd8e8/details-example.jpg -------------------------------------------------------------------------------- /e2e/protractor.conf.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Protractor configuration file, see link for more information 3 | // https://github.com/angular/protractor/blob/master/lib/config.ts 4 | 5 | const { SpecReporter } = require('jasmine-spec-reporter'); 6 | 7 | /** 8 | * @type { import("protractor").Config } 9 | */ 10 | exports.config = { 11 | allScriptsTimeout: 11000, 12 | specs: [ 13 | './src/**/*.e2e-spec.ts' 14 | ], 15 | capabilities: { 16 | 'browserName': 'chrome' 17 | }, 18 | directConnect: true, 19 | baseUrl: 'http://localhost:4200/', 20 | framework: 'jasmine', 21 | jasmineNodeOpts: { 22 | showColors: true, 23 | defaultTimeoutInterval: 30000, 24 | print: function() {} 25 | }, 26 | onPrepare() { 27 | require('ts-node').register({ 28 | project: require('path').join(__dirname, './tsconfig.json') 29 | }); 30 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } })); 31 | } 32 | }; -------------------------------------------------------------------------------- /e2e/src/app.e2e-spec.ts: -------------------------------------------------------------------------------- 1 | import { AppPage } from './app.po'; 2 | import { browser, logging } from 'protractor'; 3 | 4 | describe('workspace-project App', () => { 5 | let page: AppPage; 6 | 7 | beforeEach(() => { 8 | page = new AppPage(); 9 | }); 10 | 11 | it('should display welcome message', () => { 12 | page.navigateTo(); 13 | expect(page.getTitleText()).toEqual('angular-spacex-graphql-codegen app is running!'); 14 | }); 15 | 16 | afterEach(async () => { 17 | // Assert that there are no errors emitted from the browser 18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER); 19 | expect(logs).not.toContain(jasmine.objectContaining({ 20 | level: logging.Level.SEVERE, 21 | } as logging.Entry)); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /e2e/src/app.po.ts: -------------------------------------------------------------------------------- 1 | import { browser, by, element } from 'protractor'; 2 | 3 | export class AppPage { 4 | navigateTo() { 5 | return browser.get(browser.baseUrl) as Promise; 6 | } 7 | 8 | getTitleText() { 9 | return element(by.css('app-root .content span')).getText() as Promise; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "../out-tsc/e2e", 5 | "module": "commonjs", 6 | "target": "es5", 7 | "types": [ 8 | "jasmine", 9 | "jasminewd2", 10 | "node" 11 | ] 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration file, see link for more information 2 | // https://karma-runner.github.io/1.0/config/configuration-file.html 3 | 4 | module.exports = function (config) { 5 | config.set({ 6 | basePath: '', 7 | frameworks: ['jasmine', '@angular-devkit/build-angular'], 8 | plugins: [ 9 | require('karma-jasmine'), 10 | require('karma-chrome-launcher'), 11 | require('karma-jasmine-html-reporter'), 12 | require('karma-coverage-istanbul-reporter'), 13 | require('@angular-devkit/build-angular/plugins/karma') 14 | ], 15 | client: { 16 | clearContext: false // leave Jasmine Spec Runner output visible in browser 17 | }, 18 | coverageIstanbulReporter: { 19 | dir: require('path').join(__dirname, './coverage/angular-spacex-graphql-codegen'), 20 | reports: ['html', 'lcovonly', 'text-summary'], 21 | fixWebpackSourcePaths: true 22 | }, 23 | reporters: ['progress', 'kjhtml'], 24 | port: 9876, 25 | colors: true, 26 | logLevel: config.LOG_INFO, 27 | autoWatch: true, 28 | browsers: ['Chrome'], 29 | singleRun: false, 30 | restartOnFileChange: true 31 | }); 32 | }; 33 | -------------------------------------------------------------------------------- /list-example.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjunyel/angular-spacex-graphql-codegen/6b7bfaf0138f3558d066ea83582b399c777fd8e8/list-example.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "angular-spacex-graphql-codegen", 3 | "version": "0.0.0", 4 | "scripts": { 5 | "ng": "ng", 6 | "start": "ng serve --aot", 7 | "build": "ng build", 8 | "test": "ng test", 9 | "lint": "ng lint", 10 | "e2e": "ng e2e", 11 | "codegen": "gql-gen" 12 | }, 13 | "private": true, 14 | "dependencies": { 15 | "@angular/animations": "~8.2.5", 16 | "@angular/cdk": "~8.2.0", 17 | "@angular/common": "~8.2.5", 18 | "@angular/compiler": "~8.2.5", 19 | "@angular/core": "~8.2.5", 20 | "@angular/forms": "~8.2.5", 21 | "@angular/material": "^8.2.0", 22 | "@angular/platform-browser": "~8.2.5", 23 | "@angular/platform-browser-dynamic": "~8.2.5", 24 | "@angular/router": "~8.2.5", 25 | "apollo-angular": "^1.7.0", 26 | "apollo-angular-link-http": "^1.8.0", 27 | "apollo-cache-inmemory": "^1.6.3", 28 | "apollo-client": "^2.6.4", 29 | "apollo-link": "^1.2.13", 30 | "graphql": "^14.5.5", 31 | "graphql-tag": "^2.10.1", 32 | "hammerjs": "^2.0.8", 33 | "rxjs": "~6.4.0", 34 | "tslib": "^1.10.0", 35 | "zone.js": "~0.9.1" 36 | }, 37 | "devDependencies": { 38 | "@angular-devkit/build-angular": "~0.803.4", 39 | "@angular/cli": "~8.3.4", 40 | "@angular/compiler-cli": "~8.2.5", 41 | "@angular/language-service": "~8.2.5", 42 | "@graphql-codegen/cli": "^1.7.0", 43 | "@graphql-codegen/typescript": "^1.7.0", 44 | "@graphql-codegen/typescript-apollo-angular": "^1.7.0", 45 | "@graphql-codegen/typescript-operations": "^1.7.0", 46 | "@types/jasmine": "~3.3.8", 47 | "@types/jasminewd2": "~2.0.3", 48 | "@types/node": "~8.9.4", 49 | "codelyzer": "^5.0.0", 50 | "jasmine-core": "~3.4.0", 51 | "jasmine-spec-reporter": "~4.2.1", 52 | "karma": "~4.1.0", 53 | "karma-chrome-launcher": "~2.2.0", 54 | "karma-coverage-istanbul-reporter": "~2.0.1", 55 | "karma-jasmine": "~2.0.1", 56 | "karma-jasmine-html-reporter": "^1.4.0", 57 | "protractor": "~5.4.0", 58 | "ts-node": "~7.0.0", 59 | "tslint": "~5.15.0", 60 | "typescript": "~3.5.3" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/app/app-routing.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { Routes, RouterModule } from '@angular/router'; 3 | import { LaunchListComponent } from './launch-list/launch-list.component'; 4 | import { LaunchDetailsComponent } from './launch-details/launch-details.component'; 5 | 6 | const routes: Routes = [ 7 | { 8 | path: '', 9 | component: LaunchListComponent 10 | }, 11 | { 12 | path: ':id', 13 | component: LaunchDetailsComponent 14 | } 15 | ]; 16 | 17 | @NgModule({ 18 | imports: [RouterModule.forRoot(routes)], 19 | exports: [RouterModule] 20 | }) 21 | export class AppRoutingModule {} 22 | -------------------------------------------------------------------------------- /src/app/app.component.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjunyel/angular-spacex-graphql-codegen/6b7bfaf0138f3558d066ea83582b399c777fd8e8/src/app/app.component.css -------------------------------------------------------------------------------- /src/app/app.component.html: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/app/app.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { TestBed, async } from '@angular/core/testing'; 2 | import { RouterTestingModule } from '@angular/router/testing'; 3 | import { AppComponent } from './app.component'; 4 | 5 | describe('AppComponent', () => { 6 | beforeEach(async(() => { 7 | TestBed.configureTestingModule({ 8 | imports: [ 9 | RouterTestingModule 10 | ], 11 | declarations: [ 12 | AppComponent 13 | ], 14 | }).compileComponents(); 15 | })); 16 | 17 | it('should create the app', () => { 18 | const fixture = TestBed.createComponent(AppComponent); 19 | const app = fixture.debugElement.componentInstance; 20 | expect(app).toBeTruthy(); 21 | }); 22 | 23 | it(`should have as title 'angular-spacex-graphql-codegen'`, () => { 24 | const fixture = TestBed.createComponent(AppComponent); 25 | const app = fixture.debugElement.componentInstance; 26 | expect(app.title).toEqual('angular-spacex-graphql-codegen'); 27 | }); 28 | 29 | it('should render title', () => { 30 | const fixture = TestBed.createComponent(AppComponent); 31 | fixture.detectChanges(); 32 | const compiled = fixture.debugElement.nativeElement; 33 | expect(compiled.querySelector('.content span').textContent).toContain('angular-spacex-graphql-codegen app is running!'); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /src/app/app.component.ts: -------------------------------------------------------------------------------- 1 | import { Component } from '@angular/core'; 2 | 3 | @Component({ 4 | selector: 'app-root', 5 | templateUrl: './app.component.html', 6 | styleUrls: ['./app.component.css'] 7 | }) 8 | export class AppComponent { 9 | title = 'angular-spacex-graphql-codegen'; 10 | test = new Date(); 11 | } 12 | -------------------------------------------------------------------------------- /src/app/app.module.ts: -------------------------------------------------------------------------------- 1 | import { BrowserModule } from '@angular/platform-browser'; 2 | import { NgModule } from '@angular/core'; 3 | 4 | import { AppRoutingModule } from './app-routing.module'; 5 | import { AppComponent } from './app.component'; 6 | import { LaunchListComponent } from './launch-list/launch-list.component'; 7 | import { LaunchDetailsComponent } from './launch-details/launch-details.component'; 8 | import { GraphQLModule } from './graphql.module'; 9 | import { HttpClientModule } from '@angular/common/http'; 10 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; 11 | import { MatCardModule } from '@angular/material/card'; 12 | import { RelativeTimePipe } from './relative-time/relative-time.pipe'; 13 | 14 | @NgModule({ 15 | declarations: [AppComponent, LaunchListComponent, LaunchDetailsComponent, RelativeTimePipe], 16 | imports: [ 17 | BrowserModule, 18 | AppRoutingModule, 19 | GraphQLModule, 20 | HttpClientModule, 21 | BrowserAnimationsModule, 22 | MatCardModule 23 | ], 24 | providers: [], 25 | bootstrap: [AppComponent] 26 | }) 27 | export class AppModule {} 28 | -------------------------------------------------------------------------------- /src/app/graphql.module.ts: -------------------------------------------------------------------------------- 1 | import {NgModule} from '@angular/core'; 2 | import {ApolloModule, APOLLO_OPTIONS} from 'apollo-angular'; 3 | import {HttpLinkModule, HttpLink} from 'apollo-angular-link-http'; 4 | import {InMemoryCache} from 'apollo-cache-inmemory'; 5 | 6 | const uri = 'https://api.spacex.land/graphql/'; // <-- add the URL of the GraphQL server here 7 | export function createApollo(httpLink: HttpLink) { 8 | return { 9 | link: httpLink.create({uri}), 10 | cache: new InMemoryCache(), 11 | }; 12 | } 13 | 14 | @NgModule({ 15 | exports: [ApolloModule, HttpLinkModule], 16 | providers: [ 17 | { 18 | provide: APOLLO_OPTIONS, 19 | useFactory: createApollo, 20 | deps: [HttpLink], 21 | }, 22 | ], 23 | }) 24 | export class GraphQLModule {} 25 | -------------------------------------------------------------------------------- /src/app/launch-details/launch-details.component.css: -------------------------------------------------------------------------------- 1 | .photo-grid { 2 | padding-top: 30px; 3 | display: grid; 4 | grid-gap: 10px; 5 | grid-template-columns: repeat(auto-fill, 300px); 6 | justify-content: center; 7 | } 8 | -------------------------------------------------------------------------------- /src/app/launch-details/launch-details.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 | 4 | 5 | {{ launchDetails.mission_name }} 6 | 7 | Mission patch of {{ launchDetails.mission_name }} 14 | 15 |

{{ launchDetails.details }}

16 |
17 |
18 |
19 |
20 | Picture of {{ launchDetails.mission_name }} 28 |
29 |
30 | -------------------------------------------------------------------------------- /src/app/launch-details/launch-details.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LaunchDetailsComponent } from './launch-details.component'; 4 | 5 | describe('LaunchDetailsComponent', () => { 6 | let component: LaunchDetailsComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LaunchDetailsComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LaunchDetailsComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/launch-details/launch-details.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { ActivatedRoute } from '@angular/router'; 3 | import { map, switchMap } from 'rxjs/operators'; 4 | import { LaunchDetailsGQL } from '../services/spacexGraphql.service'; 5 | 6 | @Component({ 7 | selector: 'app-launch-details', 8 | templateUrl: './launch-details.component.html', 9 | styleUrls: ['./launch-details.component.css'], 10 | changeDetection: ChangeDetectionStrategy.OnPush 11 | }) 12 | export class LaunchDetailsComponent { 13 | constructor( 14 | private readonly route: ActivatedRoute, 15 | private readonly launchDetailsService: LaunchDetailsGQL 16 | ) {} 17 | 18 | launchDetails$ = this.route.paramMap.pipe( 19 | map((params) => params.get('id') as string), 20 | switchMap((id) => this.launchDetailsService.fetch({ id })), 21 | map((res) => res.data.launch) 22 | ); 23 | } 24 | -------------------------------------------------------------------------------- /src/app/launch-details/launch-details.graphql: -------------------------------------------------------------------------------- 1 | # src/app/launch-details/launch-details.frontend.graphql 2 | 3 | query launchDetails($id: ID!) { 4 | launch(id: $id) { 5 | id 6 | mission_name 7 | details 8 | links { 9 | flickr_images 10 | mission_patch 11 | } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/app/launch-list/launch-list.component.css: -------------------------------------------------------------------------------- 1 | .container { 2 | padding-top: 20px; 3 | display: grid; 4 | grid-gap: 30px; 5 | grid-template-columns: repeat(auto-fill, 350px); 6 | justify-content: center; 7 | } 8 | 9 | .mat-card { 10 | cursor: pointer; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/launch-list/launch-list.component.html: -------------------------------------------------------------------------------- 1 | 2 |
3 |
4 | 8 | 9 | Mission patch of {{ launch.mission_name }} 17 | {{ launch.mission_name }} 18 | {{ launch.rocket.rocket_name }} - launched 20 | {{ launch.launch_date_utc | relativeTime }} 22 | 23 | Photo of {{ launch.mission_name }} 31 | 32 |
33 |
34 |
35 | -------------------------------------------------------------------------------- /src/app/launch-list/launch-list.component.spec.ts: -------------------------------------------------------------------------------- 1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; 2 | 3 | import { LaunchListComponent } from './launch-list.component'; 4 | 5 | describe('LaunchListComponent', () => { 6 | let component: LaunchListComponent; 7 | let fixture: ComponentFixture; 8 | 9 | beforeEach(async(() => { 10 | TestBed.configureTestingModule({ 11 | declarations: [ LaunchListComponent ] 12 | }) 13 | .compileComponents(); 14 | })); 15 | 16 | beforeEach(() => { 17 | fixture = TestBed.createComponent(LaunchListComponent); 18 | component = fixture.componentInstance; 19 | fixture.detectChanges(); 20 | }); 21 | 22 | it('should create', () => { 23 | expect(component).toBeTruthy(); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /src/app/launch-list/launch-list.component.ts: -------------------------------------------------------------------------------- 1 | import { Component, ChangeDetectionStrategy } from '@angular/core'; 2 | import { map } from 'rxjs/operators'; 3 | import { PastLaunchesListGQL } from '../services/spacexGraphql.service'; 4 | 5 | @Component({ 6 | selector: 'app-launch-list', 7 | templateUrl: './launch-list.component.html', 8 | styleUrls: ['./launch-list.component.css'], 9 | changeDetection: ChangeDetectionStrategy.OnPush 10 | }) 11 | export class LaunchListComponent { 12 | constructor(private readonly pastLaunchesService: PastLaunchesListGQL) {} 13 | 14 | pastLaunches$ = this.pastLaunchesService 15 | // Please be care to not fetch too much, but this amount lets us see the img lazy loading in action 16 | .fetch({ limit: 30 }) 17 | .pipe(map((res) => res.data.launchesPast)); 18 | } 19 | -------------------------------------------------------------------------------- /src/app/launch-list/launch-list.graphql: -------------------------------------------------------------------------------- 1 | # src/app/launch-list/launch-list.graphql 2 | 3 | query pastLaunchesList($limit: Int!) { 4 | launchesPast(limit: $limit) { 5 | id 6 | mission_name 7 | links { 8 | flickr_images 9 | mission_patch_small 10 | } 11 | rocket { 12 | rocket_name 13 | } 14 | launch_date_utc 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/app/relative-time/relative-time.pipe.spec.ts: -------------------------------------------------------------------------------- 1 | import { RelativeTimePipe } from './relative-time.pipe'; 2 | 3 | describe('RelativeTimePipe', () => { 4 | it('create an instance', () => { 5 | const pipe = new RelativeTimePipe(); 6 | expect(pipe).toBeTruthy(); 7 | }); 8 | }); 9 | -------------------------------------------------------------------------------- /src/app/relative-time/relative-time.pipe.ts: -------------------------------------------------------------------------------- 1 | import { Pipe, PipeTransform } from '@angular/core'; 2 | 3 | const milliSecondsInDay = 1000 * 3600 * 24; 4 | 5 | // Cast as any because typescript typing haven't updated yet 6 | const rtf = new (Intl as any).RelativeTimeFormat('en'); 7 | 8 | @Pipe({ 9 | name: 'relativeTime' 10 | }) 11 | export class RelativeTimePipe implements PipeTransform { 12 | transform(utcTime: string): string { 13 | const diffInMillicseconds = 14 | new Date(utcTime).getTime() - new Date().getTime(); 15 | const diffInDays = Math.round(diffInMillicseconds / milliSecondsInDay); 16 | return rtf.format(diffInDays, 'day'); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/app/services/spacexGraphql.service.ts: -------------------------------------------------------------------------------- 1 | import gql from 'graphql-tag'; 2 | import { Injectable } from '@angular/core'; 3 | import * as Apollo from 'apollo-angular'; 4 | export type Maybe = T | null; 5 | /** All built-in and custom scalars, mapped to their actual values */ 6 | export type Scalars = { 7 | ID: string, 8 | String: string, 9 | Boolean: boolean, 10 | Int: number, 11 | Float: number, 12 | Date: any, 13 | ObjectID: any, 14 | }; 15 | 16 | 17 | 18 | 19 | export type Address = { 20 | __typename?: 'Address', 21 | address?: Maybe, 22 | city?: Maybe, 23 | state?: Maybe, 24 | }; 25 | 26 | export type Capsule = { 27 | __typename?: 'Capsule', 28 | id?: Maybe, 29 | landings?: Maybe, 30 | missions?: Maybe>>, 31 | original_launch?: Maybe, 32 | reuse_count?: Maybe, 33 | status?: Maybe, 34 | type?: Maybe, 35 | dragon?: Maybe, 36 | }; 37 | 38 | export type CapsuleMission = { 39 | __typename?: 'CapsuleMission', 40 | flight?: Maybe, 41 | name?: Maybe, 42 | }; 43 | 44 | export type CapsulesFind = { 45 | id?: Maybe, 46 | landings?: Maybe, 47 | mission?: Maybe, 48 | original_launch?: Maybe, 49 | reuse_count?: Maybe, 50 | status?: Maybe, 51 | type?: Maybe, 52 | }; 53 | 54 | export type Core = { 55 | __typename?: 'Core', 56 | asds_attempts?: Maybe, 57 | asds_landings?: Maybe, 58 | block?: Maybe, 59 | id?: Maybe, 60 | missions?: Maybe>>, 61 | original_launch?: Maybe, 62 | reuse_count?: Maybe, 63 | rtls_attempts?: Maybe, 64 | rtls_landings?: Maybe, 65 | status?: Maybe, 66 | water_landing?: Maybe, 67 | }; 68 | 69 | export type CoreMission = { 70 | __typename?: 'CoreMission', 71 | name?: Maybe, 72 | flight?: Maybe, 73 | }; 74 | 75 | export type CoresFind = { 76 | asds_attempts?: Maybe, 77 | asds_landings?: Maybe, 78 | block?: Maybe, 79 | id?: Maybe, 80 | missions?: Maybe, 81 | original_launch?: Maybe, 82 | reuse_count?: Maybe, 83 | rtls_attempts?: Maybe, 84 | rtls_landings?: Maybe, 85 | status?: Maybe, 86 | water_landing?: Maybe, 87 | }; 88 | 89 | 90 | export type Distance = { 91 | __typename?: 'Distance', 92 | feet?: Maybe, 93 | meters?: Maybe, 94 | }; 95 | 96 | export type Dragon = { 97 | __typename?: 'Dragon', 98 | active?: Maybe, 99 | crew_capacity?: Maybe, 100 | description?: Maybe, 101 | diameter?: Maybe, 102 | dry_mass_kg?: Maybe, 103 | dry_mass_lb?: Maybe, 104 | first_flight?: Maybe, 105 | heat_shield?: Maybe, 106 | height_w_trunk?: Maybe, 107 | id?: Maybe, 108 | launch_payload_mass?: Maybe, 109 | launch_payload_vol?: Maybe, 110 | name?: Maybe, 111 | orbit_duration_yr?: Maybe, 112 | pressurized_capsule?: Maybe, 113 | return_payload_mass?: Maybe, 114 | return_payload_vol?: Maybe, 115 | sidewall_angle_deg?: Maybe, 116 | thrusters?: Maybe>>, 117 | trunk?: Maybe, 118 | type?: Maybe, 119 | wikipedia?: Maybe, 120 | }; 121 | 122 | export type DragonHeatShield = { 123 | __typename?: 'DragonHeatShield', 124 | dev_partner?: Maybe, 125 | material?: Maybe, 126 | size_meters?: Maybe, 127 | temp_degrees?: Maybe, 128 | }; 129 | 130 | export type DragonPressurizedCapsule = { 131 | __typename?: 'DragonPressurizedCapsule', 132 | payload_volume?: Maybe, 133 | }; 134 | 135 | export type DragonThrust = { 136 | __typename?: 'DragonThrust', 137 | amount?: Maybe, 138 | fuel_1?: Maybe, 139 | fuel_2?: Maybe, 140 | pods?: Maybe, 141 | thrust?: Maybe, 142 | type?: Maybe, 143 | }; 144 | 145 | export type DragonTrunk = { 146 | __typename?: 'DragonTrunk', 147 | cargo?: Maybe, 148 | trunk_volume?: Maybe, 149 | }; 150 | 151 | export type DragonTrunkCargo = { 152 | __typename?: 'DragonTrunkCargo', 153 | solar_array?: Maybe, 154 | unpressurized_cargo?: Maybe, 155 | }; 156 | 157 | export type Force = { 158 | __typename?: 'Force', 159 | kN?: Maybe, 160 | lbf?: Maybe, 161 | }; 162 | 163 | export type HistoriesResult = { 164 | __typename?: 'HistoriesResult', 165 | result?: Maybe, 166 | data?: Maybe>>, 167 | }; 168 | 169 | export type History = { 170 | __typename?: 'History', 171 | details?: Maybe, 172 | event_date_unix?: Maybe, 173 | event_date_utc?: Maybe, 174 | id?: Maybe, 175 | links?: Maybe, 176 | title?: Maybe, 177 | flight?: Maybe, 178 | }; 179 | 180 | export type HistoryFind = { 181 | end?: Maybe, 182 | flight_number?: Maybe, 183 | id?: Maybe, 184 | start?: Maybe, 185 | }; 186 | 187 | export type Info = { 188 | __typename?: 'Info', 189 | ceo?: Maybe, 190 | coo?: Maybe, 191 | cto_propulsion?: Maybe, 192 | cto?: Maybe, 193 | employees?: Maybe, 194 | founded?: Maybe, 195 | founder?: Maybe, 196 | headquarters?: Maybe
, 197 | launch_sites?: Maybe, 198 | links?: Maybe, 199 | name?: Maybe, 200 | summary?: Maybe, 201 | test_sites?: Maybe, 202 | valuation?: Maybe, 203 | vehicles?: Maybe, 204 | }; 205 | 206 | export type InfoLinks = { 207 | __typename?: 'InfoLinks', 208 | elon_twitter?: Maybe, 209 | flickr?: Maybe, 210 | twitter?: Maybe, 211 | website?: Maybe, 212 | }; 213 | 214 | export type Landpad = { 215 | __typename?: 'Landpad', 216 | attempted_landings?: Maybe, 217 | details?: Maybe, 218 | full_name?: Maybe, 219 | id?: Maybe, 220 | landing_type?: Maybe, 221 | location?: Maybe, 222 | status?: Maybe, 223 | successful_landings?: Maybe, 224 | wikipedia?: Maybe, 225 | }; 226 | 227 | export type Launch = { 228 | __typename?: 'Launch', 229 | details?: Maybe, 230 | id?: Maybe, 231 | is_tentative?: Maybe, 232 | launch_date_local?: Maybe, 233 | launch_date_unix?: Maybe, 234 | launch_date_utc?: Maybe, 235 | launch_site?: Maybe, 236 | launch_success?: Maybe, 237 | launch_year?: Maybe, 238 | links?: Maybe, 239 | mission_id?: Maybe>>, 240 | mission_name?: Maybe, 241 | rocket?: Maybe, 242 | static_fire_date_unix?: Maybe, 243 | static_fire_date_utc?: Maybe, 244 | telemetry?: Maybe, 245 | tentative_max_precision?: Maybe, 246 | upcoming?: Maybe, 247 | ships?: Maybe>>, 248 | }; 249 | 250 | export type LaunchesPastResult = { 251 | __typename?: 'LaunchesPastResult', 252 | result?: Maybe, 253 | data?: Maybe>>, 254 | }; 255 | 256 | export type LaunchFind = { 257 | apoapsis_km?: Maybe, 258 | block?: Maybe, 259 | cap_serial?: Maybe, 260 | capsule_reuse?: Maybe, 261 | core_flight?: Maybe, 262 | core_reuse?: Maybe, 263 | core_serial?: Maybe, 264 | customer?: Maybe, 265 | eccentricity?: Maybe, 266 | end?: Maybe, 267 | epoch?: Maybe, 268 | fairings_recovered?: Maybe, 269 | fairings_recovery_attempt?: Maybe, 270 | fairings_reuse?: Maybe, 271 | fairings_reused?: Maybe, 272 | fairings_ship?: Maybe, 273 | gridfins?: Maybe, 274 | id?: Maybe, 275 | inclination_deg?: Maybe, 276 | land_success?: Maybe, 277 | landing_intent?: Maybe, 278 | landing_type?: Maybe, 279 | landing_vehicle?: Maybe, 280 | launch_date_local?: Maybe, 281 | launch_date_utc?: Maybe, 282 | launch_success?: Maybe, 283 | launch_year?: Maybe, 284 | legs?: Maybe, 285 | lifespan_years?: Maybe, 286 | longitude?: Maybe, 287 | manufacturer?: Maybe, 288 | mean_motion?: Maybe, 289 | mission_id?: Maybe, 290 | mission_name?: Maybe, 291 | nationality?: Maybe, 292 | norad_id?: Maybe, 293 | orbit?: Maybe, 294 | payload_id?: Maybe, 295 | payload_type?: Maybe, 296 | periapsis_km?: Maybe, 297 | period_min?: Maybe, 298 | raan?: Maybe, 299 | reference_system?: Maybe, 300 | regime?: Maybe, 301 | reused?: Maybe, 302 | rocket_id?: Maybe, 303 | rocket_name?: Maybe, 304 | rocket_type?: Maybe, 305 | second_stage_block?: Maybe, 306 | semi_major_axis_km?: Maybe, 307 | ship?: Maybe, 308 | side_core1_reuse?: Maybe, 309 | side_core2_reuse?: Maybe, 310 | site_id?: Maybe, 311 | site_name_long?: Maybe, 312 | site_name?: Maybe, 313 | start?: Maybe, 314 | tbd?: Maybe, 315 | tentative_max_precision?: Maybe, 316 | tentative?: Maybe, 317 | }; 318 | 319 | export type LaunchLinks = { 320 | __typename?: 'LaunchLinks', 321 | article_link?: Maybe, 322 | flickr_images?: Maybe>>, 323 | mission_patch_small?: Maybe, 324 | mission_patch?: Maybe, 325 | presskit?: Maybe, 326 | reddit_campaign?: Maybe, 327 | reddit_launch?: Maybe, 328 | reddit_media?: Maybe, 329 | reddit_recovery?: Maybe, 330 | video_link?: Maybe, 331 | wikipedia?: Maybe, 332 | }; 333 | 334 | export type Launchpad = { 335 | __typename?: 'Launchpad', 336 | attempted_launches?: Maybe, 337 | details?: Maybe, 338 | id?: Maybe, 339 | location?: Maybe, 340 | name?: Maybe, 341 | status?: Maybe, 342 | successful_launches?: Maybe, 343 | vehicles_launched?: Maybe>>, 344 | wikipedia?: Maybe, 345 | }; 346 | 347 | export type LaunchRocket = { 348 | __typename?: 'LaunchRocket', 349 | fairings?: Maybe, 350 | first_stage?: Maybe, 351 | rocket_name?: Maybe, 352 | rocket_type?: Maybe, 353 | rocket?: Maybe, 354 | second_stage?: Maybe, 355 | }; 356 | 357 | export type LaunchRocketFairings = { 358 | __typename?: 'LaunchRocketFairings', 359 | recovered?: Maybe, 360 | recovery_attempt?: Maybe, 361 | reused?: Maybe, 362 | ship?: Maybe, 363 | }; 364 | 365 | export type LaunchRocketFirstStage = { 366 | __typename?: 'LaunchRocketFirstStage', 367 | cores?: Maybe>>, 368 | }; 369 | 370 | export type LaunchRocketFirstStageCore = { 371 | __typename?: 'LaunchRocketFirstStageCore', 372 | block?: Maybe, 373 | core?: Maybe, 374 | flight?: Maybe, 375 | gridfins?: Maybe, 376 | land_success?: Maybe, 377 | landing_intent?: Maybe, 378 | landing_type?: Maybe, 379 | landing_vehicle?: Maybe, 380 | legs?: Maybe, 381 | reused?: Maybe, 382 | }; 383 | 384 | export type LaunchRocketSecondStage = { 385 | __typename?: 'LaunchRocketSecondStage', 386 | block?: Maybe, 387 | payloads?: Maybe>>, 388 | }; 389 | 390 | export type LaunchSite = { 391 | __typename?: 'LaunchSite', 392 | site_id?: Maybe, 393 | site_name_long?: Maybe, 394 | site_name?: Maybe, 395 | }; 396 | 397 | export type LaunchTelemetry = { 398 | __typename?: 'LaunchTelemetry', 399 | flight_club?: Maybe, 400 | }; 401 | 402 | export type Link = { 403 | __typename?: 'Link', 404 | article?: Maybe, 405 | reddit?: Maybe, 406 | wikipedia?: Maybe, 407 | }; 408 | 409 | export type Location = { 410 | __typename?: 'Location', 411 | latitude?: Maybe, 412 | longitude?: Maybe, 413 | name?: Maybe, 414 | region?: Maybe, 415 | }; 416 | 417 | export type Mass = { 418 | __typename?: 'Mass', 419 | kg?: Maybe, 420 | lb?: Maybe, 421 | }; 422 | 423 | export type Mission = { 424 | __typename?: 'Mission', 425 | description?: Maybe, 426 | id?: Maybe, 427 | manufacturers?: Maybe>>, 428 | name?: Maybe, 429 | twitter?: Maybe, 430 | website?: Maybe, 431 | wikipedia?: Maybe, 432 | payloads?: Maybe>>, 433 | }; 434 | 435 | export type MissionResult = { 436 | __typename?: 'MissionResult', 437 | result?: Maybe, 438 | data?: Maybe>>, 439 | }; 440 | 441 | export type MissionsFind = { 442 | id?: Maybe, 443 | manufacturer?: Maybe, 444 | name?: Maybe, 445 | payload_id?: Maybe, 446 | }; 447 | 448 | 449 | export type Payload = { 450 | __typename?: 'Payload', 451 | customers?: Maybe>>, 452 | id?: Maybe, 453 | manufacturer?: Maybe, 454 | nationality?: Maybe, 455 | norad_id?: Maybe>>, 456 | orbit_params?: Maybe, 457 | orbit?: Maybe, 458 | payload_mass_kg?: Maybe, 459 | payload_mass_lbs?: Maybe, 460 | payload_type?: Maybe, 461 | reused?: Maybe, 462 | }; 463 | 464 | export type PayloadOrbitParams = { 465 | __typename?: 'PayloadOrbitParams', 466 | apoapsis_km?: Maybe, 467 | arg_of_pericenter?: Maybe, 468 | eccentricity?: Maybe, 469 | epoch?: Maybe, 470 | inclination_deg?: Maybe, 471 | lifespan_years?: Maybe, 472 | longitude?: Maybe, 473 | mean_anomaly?: Maybe, 474 | mean_motion?: Maybe, 475 | periapsis_km?: Maybe, 476 | period_min?: Maybe, 477 | raan?: Maybe, 478 | reference_system?: Maybe, 479 | regime?: Maybe, 480 | semi_major_axis_km?: Maybe, 481 | }; 482 | 483 | export type PayloadsFind = { 484 | apoapsis_km?: Maybe, 485 | customer?: Maybe, 486 | eccentricity?: Maybe, 487 | epoch?: Maybe, 488 | inclination_deg?: Maybe, 489 | lifespan_years?: Maybe, 490 | longitude?: Maybe, 491 | manufacturer?: Maybe, 492 | mean_motion?: Maybe, 493 | nationality?: Maybe, 494 | norad_id?: Maybe, 495 | orbit?: Maybe, 496 | payload_id?: Maybe, 497 | payload_type?: Maybe, 498 | periapsis_km?: Maybe, 499 | period_min?: Maybe, 500 | raan?: Maybe, 501 | reference_system?: Maybe, 502 | regime?: Maybe, 503 | reused?: Maybe, 504 | semi_major_axis_km?: Maybe, 505 | }; 506 | 507 | export type Query = { 508 | __typename?: 'Query', 509 | capsules?: Maybe>>, 510 | capsulesPast?: Maybe>>, 511 | capsulesUpcoming?: Maybe>>, 512 | capsule?: Maybe, 513 | company?: Maybe, 514 | cores?: Maybe>>, 515 | coresPast?: Maybe>>, 516 | coresUpcoming?: Maybe>>, 517 | core?: Maybe, 518 | dragons?: Maybe>>, 519 | dragon?: Maybe, 520 | histories?: Maybe>>, 521 | historiesResult?: Maybe, 522 | history?: Maybe, 523 | landpads?: Maybe>>, 524 | landpad?: Maybe, 525 | launches?: Maybe>>, 526 | launchesPast?: Maybe>>, 527 | launchesPastResult?: Maybe, 528 | launchesUpcoming?: Maybe>>, 529 | launch?: Maybe, 530 | launchLatest?: Maybe, 531 | launchNext?: Maybe, 532 | launchpads?: Maybe>>, 533 | launchpad?: Maybe, 534 | missions?: Maybe>>, 535 | missionsResult?: Maybe, 536 | mission?: Maybe, 537 | payloads?: Maybe>>, 538 | payload?: Maybe, 539 | roadster?: Maybe, 540 | rockets?: Maybe>>, 541 | rocketsResult?: Maybe, 542 | rocket?: Maybe, 543 | ships?: Maybe>>, 544 | shipsResult?: Maybe, 545 | ship?: Maybe, 546 | }; 547 | 548 | 549 | export type QueryCapsulesArgs = { 550 | find?: Maybe, 551 | limit?: Maybe, 552 | offset?: Maybe, 553 | order?: Maybe, 554 | sort?: Maybe 555 | }; 556 | 557 | 558 | export type QueryCapsulesPastArgs = { 559 | find?: Maybe, 560 | limit?: Maybe, 561 | offset?: Maybe, 562 | order?: Maybe, 563 | sort?: Maybe 564 | }; 565 | 566 | 567 | export type QueryCapsulesUpcomingArgs = { 568 | find?: Maybe, 569 | limit?: Maybe, 570 | offset?: Maybe, 571 | order?: Maybe, 572 | sort?: Maybe 573 | }; 574 | 575 | 576 | export type QueryCapsuleArgs = { 577 | id: Scalars['ID'] 578 | }; 579 | 580 | 581 | export type QueryCoresArgs = { 582 | find?: Maybe, 583 | limit?: Maybe, 584 | offset?: Maybe, 585 | order?: Maybe, 586 | sort?: Maybe 587 | }; 588 | 589 | 590 | export type QueryCoresPastArgs = { 591 | find?: Maybe, 592 | limit?: Maybe, 593 | offset?: Maybe, 594 | order?: Maybe, 595 | sort?: Maybe 596 | }; 597 | 598 | 599 | export type QueryCoresUpcomingArgs = { 600 | find?: Maybe, 601 | limit?: Maybe, 602 | offset?: Maybe, 603 | order?: Maybe, 604 | sort?: Maybe 605 | }; 606 | 607 | 608 | export type QueryCoreArgs = { 609 | id: Scalars['ID'] 610 | }; 611 | 612 | 613 | export type QueryDragonsArgs = { 614 | limit?: Maybe, 615 | offset?: Maybe 616 | }; 617 | 618 | 619 | export type QueryDragonArgs = { 620 | id: Scalars['ID'] 621 | }; 622 | 623 | 624 | export type QueryHistoriesArgs = { 625 | find?: Maybe, 626 | limit?: Maybe, 627 | offset?: Maybe, 628 | order?: Maybe, 629 | sort?: Maybe 630 | }; 631 | 632 | 633 | export type QueryHistoriesResultArgs = { 634 | find?: Maybe, 635 | limit?: Maybe, 636 | offset?: Maybe, 637 | order?: Maybe, 638 | sort?: Maybe 639 | }; 640 | 641 | 642 | export type QueryHistoryArgs = { 643 | id: Scalars['ID'] 644 | }; 645 | 646 | 647 | export type QueryLandpadsArgs = { 648 | limit?: Maybe, 649 | offset?: Maybe 650 | }; 651 | 652 | 653 | export type QueryLandpadArgs = { 654 | id: Scalars['ID'] 655 | }; 656 | 657 | 658 | export type QueryLaunchesArgs = { 659 | find?: Maybe, 660 | limit?: Maybe, 661 | offset?: Maybe, 662 | order?: Maybe, 663 | sort?: Maybe 664 | }; 665 | 666 | 667 | export type QueryLaunchesPastArgs = { 668 | find?: Maybe, 669 | limit?: Maybe, 670 | offset?: Maybe, 671 | order?: Maybe, 672 | sort?: Maybe 673 | }; 674 | 675 | 676 | export type QueryLaunchesPastResultArgs = { 677 | find?: Maybe, 678 | limit?: Maybe, 679 | offset?: Maybe, 680 | order?: Maybe, 681 | sort?: Maybe 682 | }; 683 | 684 | 685 | export type QueryLaunchesUpcomingArgs = { 686 | find?: Maybe, 687 | limit?: Maybe, 688 | offset?: Maybe, 689 | order?: Maybe, 690 | sort?: Maybe 691 | }; 692 | 693 | 694 | export type QueryLaunchArgs = { 695 | id: Scalars['ID'] 696 | }; 697 | 698 | 699 | export type QueryLaunchLatestArgs = { 700 | offset?: Maybe 701 | }; 702 | 703 | 704 | export type QueryLaunchNextArgs = { 705 | offset?: Maybe 706 | }; 707 | 708 | 709 | export type QueryLaunchpadsArgs = { 710 | limit?: Maybe, 711 | offset?: Maybe 712 | }; 713 | 714 | 715 | export type QueryLaunchpadArgs = { 716 | id: Scalars['ID'] 717 | }; 718 | 719 | 720 | export type QueryMissionsArgs = { 721 | find?: Maybe, 722 | limit?: Maybe, 723 | offset?: Maybe 724 | }; 725 | 726 | 727 | export type QueryMissionsResultArgs = { 728 | find?: Maybe, 729 | limit?: Maybe, 730 | offset?: Maybe 731 | }; 732 | 733 | 734 | export type QueryMissionArgs = { 735 | id: Scalars['ID'] 736 | }; 737 | 738 | 739 | export type QueryPayloadsArgs = { 740 | find?: Maybe, 741 | limit?: Maybe, 742 | offset?: Maybe, 743 | order?: Maybe, 744 | sort?: Maybe 745 | }; 746 | 747 | 748 | export type QueryPayloadArgs = { 749 | id: Scalars['ID'] 750 | }; 751 | 752 | 753 | export type QueryRocketsArgs = { 754 | limit?: Maybe, 755 | offset?: Maybe 756 | }; 757 | 758 | 759 | export type QueryRocketsResultArgs = { 760 | limit?: Maybe, 761 | offset?: Maybe 762 | }; 763 | 764 | 765 | export type QueryRocketArgs = { 766 | id: Scalars['ID'] 767 | }; 768 | 769 | 770 | export type QueryShipsArgs = { 771 | find?: Maybe, 772 | limit?: Maybe, 773 | offset?: Maybe, 774 | order?: Maybe, 775 | sort?: Maybe 776 | }; 777 | 778 | 779 | export type QueryShipsResultArgs = { 780 | find?: Maybe, 781 | limit?: Maybe, 782 | offset?: Maybe, 783 | order?: Maybe, 784 | sort?: Maybe 785 | }; 786 | 787 | 788 | export type QueryShipArgs = { 789 | id: Scalars['ID'] 790 | }; 791 | 792 | export type Result = { 793 | __typename?: 'Result', 794 | totalCount?: Maybe, 795 | }; 796 | 797 | export type Roadster = { 798 | __typename?: 'Roadster', 799 | apoapsis_au?: Maybe, 800 | details?: Maybe, 801 | earth_distance_km?: Maybe, 802 | earth_distance_mi?: Maybe, 803 | eccentricity?: Maybe, 804 | epoch_jd?: Maybe, 805 | inclination?: Maybe, 806 | launch_date_unix?: Maybe, 807 | launch_date_utc?: Maybe, 808 | launch_mass_kg?: Maybe, 809 | launch_mass_lbs?: Maybe, 810 | longitude?: Maybe, 811 | mars_distance_km?: Maybe, 812 | mars_distance_mi?: Maybe, 813 | name?: Maybe, 814 | norad_id?: Maybe, 815 | orbit_type?: Maybe, 816 | periapsis_arg?: Maybe, 817 | periapsis_au?: Maybe, 818 | period_days?: Maybe, 819 | semi_major_axis_au?: Maybe, 820 | speed_kph?: Maybe, 821 | speed_mph?: Maybe, 822 | wikipedia?: Maybe, 823 | }; 824 | 825 | export type Rocket = { 826 | __typename?: 'Rocket', 827 | active?: Maybe, 828 | boosters?: Maybe, 829 | company?: Maybe, 830 | cost_per_launch?: Maybe, 831 | country?: Maybe, 832 | description?: Maybe, 833 | diameter?: Maybe, 834 | engines?: Maybe, 835 | first_flight?: Maybe, 836 | first_stage?: Maybe, 837 | height?: Maybe, 838 | id?: Maybe, 839 | landing_legs?: Maybe, 840 | mass?: Maybe, 841 | name?: Maybe, 842 | payload_weights?: Maybe>>, 843 | second_stage?: Maybe, 844 | stages?: Maybe, 845 | success_rate_pct?: Maybe, 846 | type?: Maybe, 847 | wikipedia?: Maybe, 848 | }; 849 | 850 | export type RocketEngines = { 851 | __typename?: 'RocketEngines', 852 | number?: Maybe, 853 | type?: Maybe, 854 | version?: Maybe, 855 | layout?: Maybe, 856 | engine_loss_max?: Maybe, 857 | propellant_1?: Maybe, 858 | propellant_2?: Maybe, 859 | thrust_sea_level?: Maybe, 860 | thrust_vacuum?: Maybe, 861 | thrust_to_weight?: Maybe, 862 | }; 863 | 864 | export type RocketFirstStage = { 865 | __typename?: 'RocketFirstStage', 866 | burn_time_sec?: Maybe, 867 | engines?: Maybe, 868 | fuel_amount_tons?: Maybe, 869 | reusable?: Maybe, 870 | thrust_sea_level?: Maybe, 871 | thrust_vacuum?: Maybe, 872 | }; 873 | 874 | export type RocketLandingLegs = { 875 | __typename?: 'RocketLandingLegs', 876 | number?: Maybe, 877 | material?: Maybe, 878 | }; 879 | 880 | export type RocketPayloadWeight = { 881 | __typename?: 'RocketPayloadWeight', 882 | id?: Maybe, 883 | kg?: Maybe, 884 | lb?: Maybe, 885 | name?: Maybe, 886 | }; 887 | 888 | export type RocketSecondStage = { 889 | __typename?: 'RocketSecondStage', 890 | burn_time_sec?: Maybe, 891 | engines?: Maybe, 892 | fuel_amount_tons?: Maybe, 893 | payloads?: Maybe, 894 | thrust?: Maybe, 895 | }; 896 | 897 | export type RocketSecondStagePayloadCompositeFairing = { 898 | __typename?: 'RocketSecondStagePayloadCompositeFairing', 899 | height?: Maybe, 900 | diameter?: Maybe, 901 | }; 902 | 903 | export type RocketSecondStagePayloads = { 904 | __typename?: 'RocketSecondStagePayloads', 905 | option_1?: Maybe, 906 | composite_fairing?: Maybe, 907 | }; 908 | 909 | export type RocketsResult = { 910 | __typename?: 'RocketsResult', 911 | result?: Maybe, 912 | data?: Maybe>>, 913 | }; 914 | 915 | export type Ship = { 916 | __typename?: 'Ship', 917 | abs?: Maybe, 918 | active?: Maybe, 919 | attempted_landings?: Maybe, 920 | class?: Maybe, 921 | course_deg?: Maybe, 922 | home_port?: Maybe, 923 | id?: Maybe, 924 | image?: Maybe, 925 | imo?: Maybe, 926 | missions?: Maybe>>, 927 | mmsi?: Maybe, 928 | model?: Maybe, 929 | name?: Maybe, 930 | position?: Maybe, 931 | roles?: Maybe>>, 932 | speed_kn?: Maybe, 933 | status?: Maybe, 934 | successful_landings?: Maybe, 935 | type?: Maybe, 936 | url?: Maybe, 937 | weight_kg?: Maybe, 938 | weight_lbs?: Maybe, 939 | year_built?: Maybe, 940 | }; 941 | 942 | export type ShipLocation = { 943 | __typename?: 'ShipLocation', 944 | latitude?: Maybe, 945 | longitude?: Maybe, 946 | }; 947 | 948 | export type ShipMission = { 949 | __typename?: 'ShipMission', 950 | flight?: Maybe, 951 | name?: Maybe, 952 | }; 953 | 954 | export type ShipsFind = { 955 | id?: Maybe, 956 | name?: Maybe, 957 | model?: Maybe, 958 | type?: Maybe, 959 | role?: Maybe, 960 | active?: Maybe, 961 | imo?: Maybe, 962 | mmsi?: Maybe, 963 | abs?: Maybe, 964 | class?: Maybe, 965 | weight_lbs?: Maybe, 966 | weight_kg?: Maybe, 967 | year_built?: Maybe, 968 | home_port?: Maybe, 969 | status?: Maybe, 970 | speed_kn?: Maybe, 971 | course_deg?: Maybe, 972 | latitude?: Maybe, 973 | longitude?: Maybe, 974 | successful_landings?: Maybe, 975 | attempted_landings?: Maybe, 976 | mission?: Maybe, 977 | }; 978 | 979 | export type ShipsResult = { 980 | __typename?: 'ShipsResult', 981 | result?: Maybe, 982 | data?: Maybe>>, 983 | }; 984 | 985 | export type Volume = { 986 | __typename?: 'Volume', 987 | cubic_feet?: Maybe, 988 | cubic_meters?: Maybe, 989 | }; 990 | export type LaunchDetailsQueryVariables = { 991 | id: Scalars['ID'] 992 | }; 993 | 994 | 995 | export type LaunchDetailsQuery = ( 996 | { __typename?: 'Query' } 997 | & { launch: Maybe<( 998 | { __typename?: 'Launch' } 999 | & Pick 1000 | & { links: Maybe<( 1001 | { __typename?: 'LaunchLinks' } 1002 | & Pick 1003 | )> } 1004 | )> } 1005 | ); 1006 | 1007 | export type PastLaunchesListQueryVariables = { 1008 | limit: Scalars['Int'] 1009 | }; 1010 | 1011 | 1012 | export type PastLaunchesListQuery = ( 1013 | { __typename?: 'Query' } 1014 | & { launchesPast: Maybe 1017 | & { links: Maybe<( 1018 | { __typename?: 'LaunchLinks' } 1019 | & Pick 1020 | )>, rocket: Maybe<( 1021 | { __typename?: 'LaunchRocket' } 1022 | & Pick 1023 | )> } 1024 | )>>> } 1025 | ); 1026 | 1027 | export const LaunchDetailsDocument = gql` 1028 | query launchDetails($id: ID!) { 1029 | launch(id: $id) { 1030 | id 1031 | mission_name 1032 | details 1033 | links { 1034 | flickr_images 1035 | mission_patch 1036 | } 1037 | } 1038 | } 1039 | `; 1040 | 1041 | @Injectable({ 1042 | providedIn: 'root' 1043 | }) 1044 | export class LaunchDetailsGQL extends Apollo.Query { 1045 | document = LaunchDetailsDocument; 1046 | 1047 | } 1048 | export const PastLaunchesListDocument = gql` 1049 | query pastLaunchesList($limit: Int!) { 1050 | launchesPast(limit: $limit) { 1051 | id 1052 | mission_name 1053 | links { 1054 | flickr_images 1055 | mission_patch_small 1056 | } 1057 | rocket { 1058 | rocket_name 1059 | } 1060 | launch_date_utc 1061 | } 1062 | } 1063 | `; 1064 | 1065 | @Injectable({ 1066 | providedIn: 'root' 1067 | }) 1068 | export class PastLaunchesListGQL extends Apollo.Query { 1069 | document = PastLaunchesListDocument; 1070 | 1071 | } -------------------------------------------------------------------------------- /src/assets/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjunyel/angular-spacex-graphql-codegen/6b7bfaf0138f3558d066ea83582b399c777fd8e8/src/assets/.gitkeep -------------------------------------------------------------------------------- /src/environments/environment.prod.ts: -------------------------------------------------------------------------------- 1 | export const environment = { 2 | production: true 3 | }; 4 | -------------------------------------------------------------------------------- /src/environments/environment.ts: -------------------------------------------------------------------------------- 1 | // This file can be replaced during build by using the `fileReplacements` array. 2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`. 3 | // The list of file replacements can be found in `angular.json`. 4 | 5 | export const environment = { 6 | production: false 7 | }; 8 | 9 | /* 10 | * For easier debugging in development mode, you can import the following file 11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`. 12 | * 13 | * This import should be commented out in production mode because it will have a negative impact 14 | * on performance if an error is thrown. 15 | */ 16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI. 17 | -------------------------------------------------------------------------------- /src/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arjunyel/angular-spacex-graphql-codegen/6b7bfaf0138f3558d066ea83582b399c777fd8e8/src/favicon.ico -------------------------------------------------------------------------------- /src/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AngularSpacexGraphqlCodegen 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /src/main.ts: -------------------------------------------------------------------------------- 1 | import 'hammerjs'; 2 | import { enableProdMode } from '@angular/core'; 3 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; 4 | 5 | import { AppModule } from './app/app.module'; 6 | import { environment } from './environments/environment'; 7 | 8 | if (environment.production) { 9 | enableProdMode(); 10 | } 11 | 12 | platformBrowserDynamic().bootstrapModule(AppModule) 13 | .catch(err => console.error(err)); 14 | -------------------------------------------------------------------------------- /src/polyfills.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * This file includes polyfills needed by Angular and is loaded before the app. 3 | * You can add your own extra polyfills to this file. 4 | * 5 | * This file is divided into 2 sections: 6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers. 7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main 8 | * file. 9 | * 10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that 11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera), 12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile. 13 | * 14 | * Learn more in https://angular.io/guide/browser-support 15 | */ 16 | 17 | /*************************************************************************************************** 18 | * BROWSER POLYFILLS 19 | */ 20 | 21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */ 22 | // import 'classlist.js'; // Run `npm install --save classlist.js`. 23 | 24 | /** 25 | * Web Animations `@angular/platform-browser/animations` 26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari. 27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0). 28 | */ 29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`. 30 | 31 | /** 32 | * By default, zone.js will patch all possible macroTask and DomEvents 33 | * user can disable parts of macroTask/DomEvents patch by setting following flags 34 | * because those flags need to be set before `zone.js` being loaded, and webpack 35 | * will put import in the top of bundle, so user need to create a separate file 36 | * in this directory (for example: zone-flags.ts), and put the following flags 37 | * into that file, and then add the following code before importing zone.js. 38 | * import './zone-flags.ts'; 39 | * 40 | * The flags allowed in zone-flags.ts are listed here. 41 | * 42 | * The following flags will work for all browsers. 43 | * 44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame 45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick 46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames 47 | * 48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js 49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge 50 | * 51 | * (window as any).__Zone_enable_cross_context_check = true; 52 | * 53 | */ 54 | 55 | /*************************************************************************************************** 56 | * Zone JS is required by default for Angular itself. 57 | */ 58 | import 'zone.js/dist/zone'; // Included with Angular CLI. 59 | 60 | 61 | /*************************************************************************************************** 62 | * APPLICATION IMPORTS 63 | */ 64 | -------------------------------------------------------------------------------- /src/styles.css: -------------------------------------------------------------------------------- 1 | /* You can add global styles to this file, and also import other style files */ 2 | 3 | html, body { height: 100%; } 4 | body { margin: 0; font-family: Roboto, "Helvetica Neue", sans-serif; } 5 | -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files 2 | 3 | import 'zone.js/dist/zone-testing'; 4 | import { getTestBed } from '@angular/core/testing'; 5 | import { 6 | BrowserDynamicTestingModule, 7 | platformBrowserDynamicTesting 8 | } from '@angular/platform-browser-dynamic/testing'; 9 | 10 | declare const require: any; 11 | 12 | // First, initialize the Angular testing environment. 13 | getTestBed().initTestEnvironment( 14 | BrowserDynamicTestingModule, 15 | platformBrowserDynamicTesting() 16 | ); 17 | // Then we find all the tests. 18 | const context = require.context('./', true, /\.spec\.ts$/); 19 | // And load the modules. 20 | context.keys().map(context); 21 | -------------------------------------------------------------------------------- /tsconfig.app.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/app", 5 | "types": [] 6 | }, 7 | "files": [ 8 | "src/main.ts", 9 | "src/polyfills.ts" 10 | ], 11 | "include": [ 12 | "src/**/*.ts" 13 | ], 14 | "exclude": [ 15 | "src/test.ts", 16 | "src/**/*.spec.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compileOnSave": false, 3 | "compilerOptions": { 4 | "baseUrl": "./", 5 | "outDir": "./dist/out-tsc", 6 | "sourceMap": true, 7 | "declaration": false, 8 | "downlevelIteration": true, 9 | "experimentalDecorators": true, 10 | "module": "esnext", 11 | "moduleResolution": "node", 12 | "importHelpers": true, 13 | "target": "es2015", 14 | "typeRoots": [ 15 | "node_modules/@types" 16 | ], 17 | "lib": [ 18 | "es2018", 19 | "dom", 20 | "esnext.asynciterable" 21 | ] 22 | }, 23 | "angularCompilerOptions": { 24 | "fullTemplateTypeCheck": true, 25 | "strictInjectionParameters": true 26 | } 27 | } -------------------------------------------------------------------------------- /tsconfig.spec.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "outDir": "./out-tsc/spec", 5 | "types": [ 6 | "jasmine", 7 | "node" 8 | ] 9 | }, 10 | "files": [ 11 | "src/test.ts", 12 | "src/polyfills.ts" 13 | ], 14 | "include": [ 15 | "src/**/*.spec.ts", 16 | "src/**/*.d.ts" 17 | ] 18 | } 19 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "tslint:recommended", 3 | "rules": { 4 | "array-type": false, 5 | "arrow-parens": false, 6 | "deprecation": { 7 | "severity": "warning" 8 | }, 9 | "component-class-suffix": true, 10 | "contextual-lifecycle": true, 11 | "directive-class-suffix": true, 12 | "directive-selector": [ 13 | true, 14 | "attribute", 15 | "app", 16 | "camelCase" 17 | ], 18 | "component-selector": [ 19 | true, 20 | "element", 21 | "app", 22 | "kebab-case" 23 | ], 24 | "import-blacklist": [ 25 | true, 26 | "rxjs/Rx" 27 | ], 28 | "interface-name": false, 29 | "max-classes-per-file": false, 30 | "max-line-length": [ 31 | true, 32 | 140 33 | ], 34 | "member-access": false, 35 | "member-ordering": [ 36 | true, 37 | { 38 | "order": [ 39 | "static-field", 40 | "instance-field", 41 | "static-method", 42 | "instance-method" 43 | ] 44 | } 45 | ], 46 | "no-consecutive-blank-lines": false, 47 | "no-console": [ 48 | true, 49 | "debug", 50 | "info", 51 | "time", 52 | "timeEnd", 53 | "trace" 54 | ], 55 | "no-empty": false, 56 | "no-inferrable-types": [ 57 | true, 58 | "ignore-params" 59 | ], 60 | "no-non-null-assertion": true, 61 | "no-redundant-jsdoc": true, 62 | "no-switch-case-fall-through": true, 63 | "no-use-before-declare": true, 64 | "no-var-requires": false, 65 | "object-literal-key-quotes": [ 66 | true, 67 | "as-needed" 68 | ], 69 | "object-literal-sort-keys": false, 70 | "ordered-imports": false, 71 | "quotemark": [ 72 | true, 73 | "single" 74 | ], 75 | "trailing-comma": false, 76 | "no-conflicting-lifecycle": true, 77 | "no-host-metadata-property": true, 78 | "no-input-rename": true, 79 | "no-inputs-metadata-property": true, 80 | "no-output-native": true, 81 | "no-output-on-prefix": true, 82 | "no-output-rename": true, 83 | "no-outputs-metadata-property": true, 84 | "template-banana-in-box": true, 85 | "template-no-negated-async": true, 86 | "use-lifecycle-interface": true, 87 | "use-pipe-transform-interface": true 88 | }, 89 | "rulesDirectory": [ 90 | "codelyzer" 91 | ] 92 | } --------------------------------------------------------------------------------