diff --git a/.eslintrc b/.eslintrc index 4d371f4..5725f2c 100644 --- a/.eslintrc +++ b/.eslintrc @@ -33,18 +33,18 @@ "no-param-reassign": 0, // We love param reassignment. Naming is hard. "no-shadow": 0, // Shadowing is a nice language feature. Naming is hard. "import/first": 0, // Este sorts by atom/sort-lines natural order. - "react/jsx-filename-extension": 0, // No, JSX belongs to .js files + "react/jsx-filename-extension": [1, { "extensions": [".js", ".jsx"] }], // No, JSX belongs to .js files "react/react-in-jsx-scope": 0, + "react/forbid-prop-types": [0, { "forbid": [] }], "jsx-a11y/html-has-lang": 0, // Can't recognize the Helmet. "no-confusing-arrow": 0, // This rule is super confusing. - "react/forbid-prop-types": 0, // Este is going to use Flow types. "react/no-unused-prop-types": 0, // Este is going to use Flow types. "react/jsx-indent": 0, // Damn. We need Yarn asap. "import/prefer-default-export": 0, // No. Actions can have just one action. "no-duplicate-imports": 0, // github.com/babel/eslint-plugin-babel/issues/59#issuecomment-230118848 "import/no-duplicates": 2, // Rules for functional programming. We do not need Object.freeze. - "fp/no-mutating-assign": 2, + "fp/no-mutating-assign": 2 // TODO: Can't be enabled now, it requires a lot of refactoring. // "fp/no-mutating-methods": 2, // "fp/no-mutation": ["error", { diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..723ef36 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.idea \ No newline at end of file diff --git a/.iron/config.json b/.iron/config.json new file mode 100644 index 0000000..874b949 --- /dev/null +++ b/.iron/config.json @@ -0,0 +1,22 @@ +{ + "engines": { + "html": "html", + "js": "js", + "css": "css" + }, + + "template": { + "html": "true", + "js": "true", + "css": "true" + }, + + "route": { + "controller": "true", + "template": "true" + }, + + "generator": { + "comments": "true" + } +} diff --git a/README.md b/README.md index 5a3a22c..2d83821 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,10 @@ -# Meteor React Redux Webpack Starter Kit +# IDE. Front-end side. -> Starter kit for universal full–fledged React apps. One stack for browser, mobile, server. +## Overview +This part - front-end side of IDE that incapsulates all external services - Container Management, Workspace App, etc. This is Meteor.js application uses DB that shared with IOServer for sync containers and servers statuses. +## Installation and start > You don't have to start with everything. MRRWS kit is perfect even for plain static pages. You can gracefully add any platform later. MRRWS kit mission is simple: **Help startups to deliver minimal valuable product asap with the state of the art real-time universal app stack with meteor**. @@ -35,12 +37,14 @@ npm install cd app && npm install ``` -- Add config file - "***settings.json***" to development or production environment (./config/development or ./config/production). +- Add config file - "***settings.json***" to development or prodction environment (./config/development or ./config/production). + ```json { "public": { "sentryUrl": "https://********************@app.getsentry.com/***", "googleAnalyticsId": "UA-XXXXXXX-X", + "io": "http://localhost:4000/manager", "logLevel": "debug" }, "private": { @@ -58,6 +62,14 @@ cd app && npm install } ``` +- Create database - "***ide***" in MongoDB. + +### Run Application +Before application run check *start* script in ***./app/package.json*** file. +```bash +cd app && npm start +``` + ### Start ``` cd app diff --git a/app/.meteor/packages b/app/.meteor/packages index 9a12b49..ef7fe03 100644 --- a/app/.meteor/packages +++ b/app/.meteor/packages @@ -46,6 +46,11 @@ react-meteor-data std:accounts-ui std:accounts-bootstrap browser-policy@1.0.9 +splendido:accounts-meld +splendido:accounts-meld-client-bootstrap +pauli:accounts-linkedin +jakobloekke:rabbitmq random +reywood:publish-composite apollo webpack:typescript diff --git a/app/.meteor/versions b/app/.meteor/versions index c8062dd..7acea26 100644 --- a/app/.meteor/versions +++ b/app/.meteor/versions @@ -54,6 +54,7 @@ htmljs@1.0.11 http@1.2.10 id-map@1.0.9 insecure@1.0.7 +jakobloekke:rabbitmq@0.1.2 jquery@1.11.10 launch-screen@1.0.12 less@2.7.6 @@ -76,12 +77,15 @@ modules@0.7.7 modules-runtime@0.7.7 mongo@1.1.14 mongo-id@1.0.6 +mongo-livedata@1.0.12 npm-bcrypt@0.9.2 npm-mongo@2.2.11_2 oauth@1.1.12 oauth2@1.1.11 observe-sequence@1.0.14 ordered-dict@1.0.9 +pauli:accounts-linkedin@1.3.1 +pauli:linkedin@1.3.1 practicalmeteor:chai@2.1.0_1 practicalmeteor:loglevel@1.2.0_2 practicalmeteor:mocha@2.4.5_6 @@ -98,6 +102,7 @@ reactive-var@1.0.11 reactrouter:react-router-ssr@3.1.6 reload@1.1.11 retry@1.0.9 +reywood:publish-composite@1.4.2 routepolicy@1.0.12 service-configuration@1.0.11 session@1.1.7 @@ -106,6 +111,9 @@ shell-server@0.2.1 softwarerero:accounts-t9n@1.3.5 spacebars@1.0.13 spacebars-compiler@1.0.13 +splendido:accounts-emails-field@1.2.0 +splendido:accounts-meld@1.3.1 +splendido:accounts-meld-client-bootstrap@1.0.4 srp@1.0.10 standard-minifier-css@1.3.2 standard-minifier-js@1.2.1 diff --git a/app/lib/i18n/messages/src/MainApp/client/app/layouts/Footer.json b/app/lib/i18n/messages/src/IDEApp/client/App/layouts/Footer.json similarity index 100% rename from app/lib/i18n/messages/src/MainApp/client/app/layouts/Footer.json rename to app/lib/i18n/messages/src/IDEApp/client/App/layouts/Footer.json diff --git a/app/lib/i18n/messages/src/IDEApp/common/app/linksMessages.json b/app/lib/i18n/messages/src/IDEApp/common/app/linksMessages.json new file mode 100644 index 0000000..803508e --- /dev/null +++ b/app/lib/i18n/messages/src/IDEApp/common/app/linksMessages.json @@ -0,0 +1,30 @@ +[ + { + "id": "app.links.intl", + "defaultMessage": "Intl" + }, + { + "id": "app.links.home", + "defaultMessage": "Home" + }, + { + "id": "app.links.signIn", + "defaultMessage": "Sign in" + }, + { + "id": "app.links.signOut", + "defaultMessage": "Sign out" + }, + { + "id": "app.links.pricing", + "defaultMessage": "Pricing" + }, + { + "id": "app.links.features", + "defaultMessage": "Features" + }, + { + "id": "app.links.blog", + "defaultMessage": "Blog" + } +] \ No newline at end of file diff --git a/app/lib/i18n/messages/src/MainApp/client/App/layouts/Footer.json b/app/lib/i18n/messages/src/MainApp/client/App/layouts/Footer.json new file mode 100644 index 0000000..70c2896 --- /dev/null +++ b/app/lib/i18n/messages/src/MainApp/client/App/layouts/Footer.json @@ -0,0 +1,6 @@ +[ + { + "id": "footer.madeByHtml", + "defaultMessage": "Made with love by" + } +] \ No newline at end of file diff --git a/app/package.json b/app/package.json index 2a95f62..4f43db2 100644 --- a/app/package.json +++ b/app/package.json @@ -21,31 +21,47 @@ "bootstrap": "^3.3.7", "cdm-logger": "1.0.7", "cheerio": "^0.20.0", + "classnames": "^2.2.5", + "codemirror": "^5.16.0", "cookie-monster": "^0.2.0", "cookie-parser": "^1.4.3", "dataloader": "^1.2.0", "deepmerge": "^0.2.10", "diff-match-patch": "^1.0.0", + "dockerode": "^2.3.1", "express": "^4.14.0", "formatjs": "^0.1.1", + "fs_events": "^1.0.3", "graphql": "^0.8.2", + "graphql-custom-types": "^0.7.1", "graphql-schema-collector": "0.2.4", "graphql-server-express": "^0.4.3", + "graphql-subscriptions": "^0.2.2", "graphql-tag": "^1.1.2", "graphql-tools": "^0.8.4", "graphql-typings": "0.0.1-beta-2", + "immutability-helper": "^2.0.0", +<<<<<<< HEAD + "immutable": "^3.8.1", +======= +>>>>>>> e6aac71... changed to use graphql "intl-locales-supported": "^1.0.0", "intl-messageformat": "^1.3.0", "intl-relativeformat": "^1.3.0", + "intro.js": "^2.1.0", "invariant": "^2.2.1", "keymaster": "^1.6.2", "localforage": "^1.4.3", + "lodash": "^4.17.2", "lodash.debounce": "^4.0.7", "make-error": "^1.2.1", "meteor-node-stubs": "^0.2.3", + "meteor-rxjs": "^0.4.5", "mime": "^1.3.4", "nconf": "^0.8.4", "node-sass": "^3.8.0", + "pkginfo": "^0.4.0", + "portscanner-plus": "^0.2.1", "ramda": "^0.22.1", "randomstring": "^1.1.5", "raven-js": "^3.3.0", @@ -62,6 +78,8 @@ "react-apollo": "^0.7.0", "react-bootstrap": "^0.30.2", "react-codemirror": "^0.2.6", + "react-contextmenu": "^1.6.3", + "react-cookie": "^1.0.4", "react-dom": "^15.2.0", "react-ga": "^2.1.2", "react-helmet": "^3.1.0", @@ -75,9 +93,11 @@ "react-router": "^3.0.0", "react-router-bootstrap": "^0.23.1", "react-router-redux": "^4.0.7", + "react-split-pane": "^0.1.44", + "readdir-plus": "^0.4.1", "rebass": "^0.3.3", "recompose": "^0.20.2", - "redux": "^3.5.2", + "redux": "^3.6.0", "redux-devtools": "^3.3.1", "redux-devtools-dock-monitor": "^1.1.1", "redux-devtools-log-monitor": "^1.0.11", @@ -93,10 +113,16 @@ "rxjs": "^5.0.1", "sass-loader": "^4.0.0", "shortid": "^2.2.6", + "socket.io-client": "^1.4.8", + "ssh2": "^0.5.0", + "subscriptions-transport-ws": "^0.3.1", + "superagent": "^2.3.0", + "superagent-defaults": "^0.1.14", "tracker-component": "^1.3.21", "transit-immutable-js": "^0.6.0", "transit-js": "^0.8.846", - "validator": "^5.5.0" + "validator": "^5.5.0", + "xterm": "^2.1.0" }, "devDependencies": { "apollo-codegen": "^0.9.6", @@ -112,6 +138,7 @@ "babel-preset-react": "^6.3.13", "babel-preset-stage-0": "^6.3.13", "babel-runtime": "^6.18.0", + "bunyan-debug-stream": "^1.0.7", "css-loader": "^0.23.0", "enzyme": "^2.4.1", "eslint": "^3.12.2", diff --git a/app/packages/meteor-integration/.versions b/app/packages/meteor-integration/.versions new file mode 100644 index 0000000..aa143c5 --- /dev/null +++ b/app/packages/meteor-integration/.versions @@ -0,0 +1,71 @@ +accounts-base@1.2.9 +allow-deny@1.0.5 +apollo@0.2.0 +autoupdate@1.2.11 +babel-compiler@6.9.0 +babel-runtime@0.1.10 +base64@1.0.9 +binary-heap@1.0.9 +blaze@2.1.8 +blaze-tools@1.0.9 +boilerplate-generator@1.0.9 +caching-compiler@1.0.6 +caching-html-compiler@1.0.6 +callback-hook@1.0.9 +check@1.2.3 +coffeescript@1.1.3 +ddp@1.2.5 +ddp-client@1.2.9 +ddp-common@1.2.6 +ddp-rate-limiter@1.0.5 +ddp-server@1.2.9 +deps@1.0.12 +diff-sequence@1.0.6 +ecmascript@0.5.7 +ecmascript-runtime@0.3.12 +ejson@1.0.12 +geojson-utils@1.0.9 +html-tools@1.0.10 +htmljs@1.0.10 +http@1.1.8 +id-map@1.0.8 +jquery@1.11.9 +local-test:apollo@0.2.0 +localstorage@1.0.11 +logging@1.1.14 +meteor@1.2.16 +minifier-js@1.1.13 +minimongo@1.0.17 +modules@0.7.5 +modules-runtime@0.7.5 +mongo@1.1.10 +mongo-id@1.0.5 +npm-mongo@1.5.45 +observe-sequence@1.0.12 +ordered-dict@1.0.8 +practicalmeteor:chai@2.1.0_1 +practicalmeteor:loglevel@1.2.0_2 +practicalmeteor:mocha@2.1.0_7 +practicalmeteor:mocha-core@0.1.4 +practicalmeteor:sinon@1.14.1_2 +promise@0.8.3 +random@1.0.10 +rate-limit@1.0.5 +reactive-dict@1.1.8 +reactive-var@1.0.10 +reload@1.1.10 +retry@1.0.8 +routepolicy@1.0.11 +service-configuration@1.0.10 +session@1.1.6 +spacebars@1.0.12 +spacebars-compiler@1.0.12 +templating@1.1.13 +templating-tools@1.0.4 +tmeasday:check-npm-versions@0.3.1 +tracker@1.1.0 +ui@1.0.11 +underscore@1.0.9 +url@1.0.10 +webapp@1.3.10 +webapp-hashing@1.0.9 diff --git a/app/packages/meteor-integration/CHANGELOG.md b/app/packages/meteor-integration/CHANGELOG.md new file mode 100644 index 0000000..30da16d --- /dev/null +++ b/app/packages/meteor-integration/CHANGELOG.md @@ -0,0 +1,50 @@ +# Change Log +All notable changes to this project will be documented in this file. [*File syntax*](http://keepachangelog.com/). +This project adheres to [Semantic Versioning](http://semver.org/). + +## vNEXT + +## [0.2.1] - 2016-12-23 +### Added + +- Support for `v0.8.x` of `graphql` [#54](https://github.com/apollostack/meteor-integration/pull/54) +- When user is not logged in, provide `{}` as context [#55](https://github.com/apollostack/meteor-integration/pull/55) + +## [0.2.0] - 2016-11-04 +### Updated + +- `apollo-client` [v0.5.x](https://github.com/apollostack/apollo-client/blob/master/CHANGELOG.md#v050) +- Updated createNetworkInterface call to match new signature ([@jasonphillips](https://github.com/jasonphillips) in [#43](https://github.com/apollostack/meteor-integration/pull/43)). +- `graphql-server` [v0.4.2](https://github.com/apollostack/graphql-server/blob/master/CHANGELOG.md#v042) + +### Added + +- Added the logged-in user's doc to `context.user` + +## [0.1.2] - 2016-10-04 +### Added + +- Pass a function to configure the express server in createApolloServer ([@nicolaslopezj](https://github.com/nicolaslopezj) in [#32](https://github.com/apollostack/meteor-integration/pull/32)). +- Automatically pass Meteor authentication in GraphiQL ([@nicolaslopezj](https://github.com/nicolaslopezj) in [#35](https://github.com/apollostack/meteor-integration/pull/35)). + +## [0.1.1] - 2016-09-21 +### Fixed + +- Fix userId persisting in options.context (reported in [#37](https://github.com/apollostack/meteor-integration/pull/37)) + +## [0.1.0] - 2016-09-09 +### Updated + +- `apollo-server` [v0.2.x](https://github.com/apollostack/apollo-server/blob/cc15ebfb1c9637989e09976c8416b4fd5c2b6728/CHANGELOG.md) + - Updated interface to reflect `apollo-server` refactor. +- `apollo-client` [v0.4.x](https://github.com/apollostack/apollo-client/blob/master/CHANGELOG.md#v040) + +## [0.0.4] - 2016-08-24 +### Fixed + +- Fixed global auth issue + +## [0.0.2] - 2016-06-17 +### Fixed + +- Fix dependencies #17 diff --git a/app/packages/meteor-integration/README.md b/app/packages/meteor-integration/README.md new file mode 100644 index 0000000..dcee18f --- /dev/null +++ b/app/packages/meteor-integration/README.md @@ -0,0 +1,26 @@ +Use the [Apollo Stack](http://dev.apollodata.com/) in your [Meteor](https://www.meteor.com/) app. + +```sh +meteor add apollo +``` + +# Docs + +**[The docs](http://dev.apollodata.com/core/meteor.html)** + +# Package dev + +## Tests + +TODO broken, see #3 + +```bash +git clone git@github.com:apollostack/meteor-integration.git +cd meteor-integration +meteor test-packages ./ --driver-package practicalmeteor:mocha +open localhost:3000 +``` + +## Credits + +[Contributors](https://github.com/apollostack/meteor-integration/graphs/contributors) diff --git a/app/packages/meteor-integration/check-npm.js b/app/packages/meteor-integration/check-npm.js new file mode 100644 index 0000000..985f7c0 --- /dev/null +++ b/app/packages/meteor-integration/check-npm.js @@ -0,0 +1,19 @@ +import { Meteor } from 'meteor/meteor'; +import { checkNpmVersions } from 'meteor/tmeasday:check-npm-versions'; + +if (Meteor.isClient) { + checkNpmVersions({ + 'apollo-client': '^0.5.0', + }, 'apollo'); +} else { + checkNpmVersions({ + 'graphql-server-express': '^0.4.3', + "body-parser": "^1.15.2", + "express": "^4.14.0", + "graphql": "^0.7.0 || ^0.8.0", + "graphql-tools": "^0.8.0", + "subscriptions-transport-ws": "^0.3.0", + "graphql-tag": "^1.1.0", + "graphql-subscriptions": "^0.2.0" + }, 'apollo'); +} diff --git a/app/packages/meteor-integration/main-client.js b/app/packages/meteor-integration/main-client.js new file mode 100644 index 0000000..9293ae3 --- /dev/null +++ b/app/packages/meteor-integration/main-client.js @@ -0,0 +1,117 @@ +import './check-npm.js'; + +import { createNetworkInterface } from 'apollo-client'; +import { Accounts } from 'meteor/accounts-base'; +import { _ } from 'meteor/underscore'; +<<<<<<< HEAD +<<<<<<< HEAD +import { Meteor } from 'meteor/meteor'; +======= +>>>>>>> fe75b6f... with apollo subscription +======= +import { Meteor } from 'meteor/meteor'; +>>>>>>> 4dbaabf... fixed SSR +import { print } from 'graphql-tag/printer'; +import { Client } from 'subscriptions-transport-ws'; + +const defaultNetworkInterfaceConfig = { + path: '/graphql', + options: {}, + useMeteorAccounts: true, + useSubscription: true, +}; + +const getDefaultWsClient = () => new Client('ws://localhost:8080'); + +export const createMeteorNetworkInterface = (givenConfig) => { + const config = _.extend(defaultNetworkInterfaceConfig, givenConfig); + const wsClient = givenConfig && givenConfig.wsClient ? givenConfig.wsClient : getDefaultWsClient(); + // absoluteUrl adds a '/', so let's remove it first + let path = config.path; + if (path[0] === '/') { + path = path.slice(1); + } + + // For SSR + const uri = Meteor.absoluteUrl(path); + const networkInterface = createNetworkInterface({ uri }); + + if (config.useMeteorAccounts) { + networkInterface.use([{ + applyMiddleware(request, next) { +<<<<<<< HEAD +<<<<<<< HEAD + // Accounts._storedLoginToken refers to local storage existing only client-side + const currentUserToken = config.loginToken ? config.loginToken : Meteor.isClient ? Accounts._storedLoginToken() : null; +======= + const currentUserToken = Accounts._storedLoginToken() ? Accounts._storedLoginToken() : null; +>>>>>>> fe75b6f... with apollo subscription +======= + // Accounts._storedLoginToken refers to local storage existing only client-side + const currentUserToken = config.loginToken ? config.loginToken : Meteor.isClient ? Accounts._storedLoginToken() : null; +>>>>>>> e6aac71... changed to use graphql + + if (!currentUserToken) { + next(); + return; + } + + if (!request.options.headers) { + request.options.headers = new Headers(); + } + + request.options.headers.Authorization = currentUserToken; + + next(); + }, + }]); + } + + if (config.useSubscription) { + return _.extend(networkInterface, { + subscribe: (request, handler) => wsClient.subscribe({ + query: print(request.query), + variables: request.variables, + }, handler), + unsubscribe: (id) => { + wsClient.unsubscribe(id); + }, + }); + } + return networkInterface; +}; + +export const meteorClientConfig = (networkInterfaceConfig) => { +<<<<<<< HEAD +<<<<<<< HEAD + return { + ssrMode: Meteor.isServer, + networkInterface: createMeteorNetworkInterface(networkInterfaceConfig), +======= + const networkInterface = createMeteorNetworkInterface(networkInterfaceConfig); + let { initialState } = networkInterface; + if(initialState){ + // Temporary workaround for bug in AC@0.5.0: https://github.com/apollostack/apollo-client/issues/845 + delete initialState.apollo.queries; + delete initialState.apollo.mutations; + } + + return { + networkInterface, + initialState, +>>>>>>> fe75b6f... with apollo subscription +======= + return { + ssrMode: Meteor.isServer, + networkInterface: createMeteorNetworkInterface(networkInterfaceConfig), +>>>>>>> 4dbaabf... fixed SSR + // Default to using Mongo _id, must use _id for queries. + dataIdFromObject: (result) => { + if (result._id && result.__typename) { + const dataId = result.__typename + result._id; + return dataId; + } + return null; + }, + }; +}; diff --git a/app/packages/meteor-integration/main-server.js b/app/packages/meteor-integration/main-server.js new file mode 100644 index 0000000..ede3f7e --- /dev/null +++ b/app/packages/meteor-integration/main-server.js @@ -0,0 +1,124 @@ +import './check-npm.js'; + +import { graphqlExpress, graphiqlExpress } from 'graphql-server-express'; +import bodyParser from 'body-parser'; +import express from 'express'; +import { createServer } from 'http'; +import { Meteor } from 'meteor/meteor'; +import { WebApp } from 'meteor/webapp'; +import { check } from 'meteor/check'; +import { Accounts } from 'meteor/accounts-base'; +import { _ } from 'meteor/underscore'; +import { SubscriptionServer } from 'subscriptions-transport-ws'; + +export { meteorClientConfig, createMeteorNetworkInterface } from './main-client'; + +const defaultConfig = { + path: '/graphql', + maxAccountsCacheSizeInMB: 1, + graphiql : Meteor.isDevelopment, + graphiqlPath : '/graphiql', + graphiqlOptions : { + passHeader : "'Authorization': localStorage['Meteor.loginToken']" + }, + useSubscription: true, + subscriptionPort: 8080, + configServer: (graphQLServer) => {}, +}; + +const defaultOptions = { + formatError: e => ({ + message: e.message, + locations: e.locations, + path: e.path + }), +}; + +if (Meteor.isDevelopment) { + defaultOptions.debug = true; +} + +export const createApolloServer = (givenOptions = {}, givenConfig = {}) => { + const { subscriptionManager, ...restOfConfig } = givenConfig; + let graphiqlOptions = Object.assign({}, defaultConfig.graphiqlOptions, restOfConfig.graphiqlOptions); + let config = Object.assign({}, defaultConfig, restOfConfig); + config.graphiqlOptions = graphiqlOptions; + + const graphQLServer = express(); + + config.configServer(graphQLServer) + + // GraphQL endpoint + graphQLServer.use(config.path, bodyParser.json(), graphqlExpress(async (req) => { + let options, + user = null; + + if (_.isFunction(givenOptions)) + options = givenOptions(req); + else + options = givenOptions; + + // Merge in the defaults + options = Object.assign({}, defaultOptions, options); + if (options.context) { + // don't mutate the context provided in options + options.context = Object.assign({}, options.context); + } else { + options.context = {}; + } + + // Get the token from the header + if (req.headers.authorization) { + const token = req.headers.authorization; + check(token, String); + const hashedToken = Accounts._hashLoginToken(token); + + // Get the user from the database + user = await Meteor.users.findOne( + {"services.resume.loginTokens.hashedToken": hashedToken} + ); + + if (user) { + const loginToken = _.findWhere(user.services.resume.loginTokens, { hashedToken }); + const expiresAt = Accounts._tokenExpiration(loginToken.when); + const isExpired = expiresAt < new Date(); + + if (!isExpired) { + options.context.userId = user._id; + options.context.user = user; + } + } + } + + return options; + + })); + + // Start GraphiQL if enabled + if (config.graphiql) { + graphQLServer.use(config.graphiqlPath, graphiqlExpress(_.extend(config.graphiqlOptions, {endpointURL : config.path}))); + } + + // create http server for subscription + const server = createServer(graphQLServer); + + // This binds the specified paths to the Express server running Apollo + GraphiQL + WebApp.connectHandlers.use(Meteor.bindEnvironment(graphQLServer)); + + // Add subscriptionManager here + if (config.useSubscription) { + if (!subscriptionManager) { + throw new Meteor.Error('SubscriptionManager which is mandatory missing.'); + } + new SubscriptionServer({ + subscriptionManager, + }, server); + try { + server.listen(config.subscriptionPort, () => { + console.log('Subscription manager running ' + config.subscriptionPort); + }); + } catch (e) { + console.log(e); + } + } +}; diff --git a/app/packages/meteor-integration/package.js b/app/packages/meteor-integration/package.js new file mode 100644 index 0000000..6be302c --- /dev/null +++ b/app/packages/meteor-integration/package.js @@ -0,0 +1,27 @@ +Package.describe({ + name: 'apollo', + version: '0.2.1', + summary: ' 🚀 Add Apollo to your Meteor app', + git: 'https://github.com/apollostack/meteor-integration' +}); + +Package.onUse(function(api) { + api.versionsFrom('1.4.0.1'); + api.use(['ecmascript', + 'underscore', + 'accounts-base', + 'tmeasday:check-npm-versions@0.3.1']); + + api.mainModule('main-client.js', 'client'); + api.mainModule('main-server.js', 'server'); +}); + +Package.onTest(function(api) { + api.use(['ecmascript', + 'practicalmeteor:mocha', + 'practicalmeteor:chai', + 'apollo']); + + api.mainModule('tests/client.js', 'client'); + api.mainModule('tests/server.js', 'server'); +}); diff --git a/app/packages/meteor-integration/tests/client.js b/app/packages/meteor-integration/tests/client.js new file mode 100644 index 0000000..24fd71a --- /dev/null +++ b/app/packages/meteor-integration/tests/client.js @@ -0,0 +1,12 @@ +import { assert } from 'meteor/practicalmeteor:chai'; + +import { createMeteorNetworkInterface } from 'meteor/apollo'; + +describe('client', function() { + + it('works', function() { + assert.ok(createMeteorNetworkInterface()); + }); + +}); + diff --git a/app/packages/meteor-integration/tests/server.js b/app/packages/meteor-integration/tests/server.js new file mode 100644 index 0000000..1efc010 --- /dev/null +++ b/app/packages/meteor-integration/tests/server.js @@ -0,0 +1,12 @@ +import { assert } from 'meteor/practicalmeteor:chai'; + +import { createApolloServer } from 'meteor/apollo'; + +describe('server', function() { + + it('works', function() { + assert.ok(createApolloServer()); + }); + +}); + diff --git a/app/packages/meteor-react-router-ssr/README.md b/app/packages/meteor-react-router-ssr/README.md index 576e1ed..5d41c47 100644 --- a/app/packages/meteor-react-router-ssr/README.md +++ b/app/packages/meteor-react-router-ssr/README.md @@ -34,6 +34,11 @@ Your main `` node of your application.
- `dehydrateHook` [function() : data]: Supply data that should be dehydrated and sent to client. - `fetchDataHook` [function(components) : Array]: Trigger the fetchData on your components that have it - `preRender` [function(req, res)]: Executed just before the renderToString +<<<<<<< HEAD +- `dataLoader` [function(req, res, app)]: Executed just after the wrapperHook to populate any data. +======= +- `dataLoader` [function(req, res)]: Executed just after the wrapperHook to populate any data. +>>>>>>> cb1ed95... updated readme - `postRender` [function(req, res)]: Executed just after the renderToString - `dontMoveScripts` [bool]: Keep the script inside the head tag instead of moving it at the end of the body - `disableSSR` [bool]: Disable server-side rendering, in case the application depends on code which doesn't work on the server. diff --git a/app/packages/meteor-react-router-ssr/lib/client.jsx b/app/packages/meteor-react-router-ssr/lib/client.jsx index 7261279..c88810c 100644 --- a/app/packages/meteor-react-router-ssr/lib/client.jsx +++ b/app/packages/meteor-react-router-ssr/lib/client.jsx @@ -46,15 +46,17 @@ const ReactRouterSSR = { }); } - let app = ( + let appGenerator = (addProps) => ( + {...clientOptions.props} + {...addProps } /> ); + let app; if (typeof clientOptions.wrapperHook === 'function') { - app = clientOptions.wrapperHook(app); + app = clientOptions.wrapperHook(appGenerator); } if (typeof clientOptions.renderHook === 'function') { diff --git a/app/packages/meteor-react-router-ssr/lib/server.jsx b/app/packages/meteor-react-router-ssr/lib/server.jsx index f44f538..5c3ed9f 100644 --- a/app/packages/meteor-react-router-ssr/lib/server.jsx +++ b/app/packages/meteor-react-router-ssr/lib/server.jsx @@ -203,11 +203,34 @@ function generateSSRData(clientOptions, serverOptions, req, res, renderProps) { ...serverOptions.props }; - fetchComponentData(serverOptions, renderProps); + // Instead of fetchComponentData we need to fetch from Apollo Data + //fetchComponentData(serverOptions, renderProps); +<<<<<<< HEAD +<<<<<<< HEAD + let appGenerator = (addProps) => ; +======= let app = ; +>>>>>>> 4dbaabf... fixed SSR +======= + let appGenerator = (addProps) => ; +>>>>>>> 0f9faf8... to fix loading props in wrapperHook + let app; if (typeof clientOptions.wrapperHook === 'function') { - app = clientOptions.wrapperHook(app); + app = clientOptions.wrapperHook(appGenerator); +<<<<<<< HEAD + } + + // Adding new parameter dataLoader for loading data through Apollo + if (serverOptions.dataLoader) { + serverOptions.dataLoader(req, res, app); +======= +>>>>>>> 0f9faf8... to fix loading props in wrapperHook + } + + // Adding new parameter dataLoader for loading data through Apollo + if (serverOptions.dataLoader) { + serverOptions.dataLoader(req, res, app); } if (!serverOptions.disableSSR){ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-Black.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-Black.ttf new file mode 100755 index 0000000..ea73e60 Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-Black.ttf differ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-Bold.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-Bold.ttf new file mode 100755 index 0000000..a56f1fa Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-Bold.ttf differ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-ExtraLight.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-ExtraLight.ttf new file mode 100755 index 0000000..f409b71 Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-ExtraLight.ttf differ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-Light.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-Light.ttf new file mode 100755 index 0000000..51eb963 Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-Light.ttf differ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-Medium.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-Medium.ttf new file mode 100755 index 0000000..1ee45eb Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-Medium.ttf differ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-Regular.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-Regular.ttf new file mode 100755 index 0000000..b2cff92 Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-Regular.ttf differ diff --git a/app/public/fonts/Source_Code_Pro/SourceCodePro-Semibold.ttf b/app/public/fonts/Source_Code_Pro/SourceCodePro-Semibold.ttf new file mode 100755 index 0000000..b425f9c Binary files /dev/null and b/app/public/fonts/Source_Code_Pro/SourceCodePro-Semibold.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-Black.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Black.ttf new file mode 100755 index 0000000..cb89a2d Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Black.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-BlackItalic.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-BlackItalic.ttf new file mode 100755 index 0000000..c719243 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-BlackItalic.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-Bold.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Bold.ttf new file mode 100755 index 0000000..50d81bd Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Bold.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-BoldItalic.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-BoldItalic.ttf new file mode 100755 index 0000000..d20dd0c Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-BoldItalic.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-ExtraLight.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-ExtraLight.ttf new file mode 100755 index 0000000..bb4176c Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-ExtraLight.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-ExtraLightItalic.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-ExtraLightItalic.ttf new file mode 100755 index 0000000..2c34f3b Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-ExtraLightItalic.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-Italic.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Italic.ttf new file mode 100755 index 0000000..e5a1a86 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Italic.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf new file mode 100755 index 0000000..5f64679 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Light.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-LightItalic.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-LightItalic.ttf new file mode 100755 index 0000000..88a6778 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-LightItalic.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf new file mode 100755 index 0000000..91e9ea5 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Regular.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-Semibold.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Semibold.ttf new file mode 100755 index 0000000..5020594 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-Semibold.ttf differ diff --git a/app/public/fonts/Source_Sans_Pro/SourceSansPro-SemiboldItalic.ttf b/app/public/fonts/Source_Sans_Pro/SourceSansPro-SemiboldItalic.ttf new file mode 100755 index 0000000..2c5ad30 Binary files /dev/null and b/app/public/fonts/Source_Sans_Pro/SourceSansPro-SemiboldItalic.ttf differ diff --git a/app/public/fonts/entypo/entypo.eot b/app/public/fonts/entypo/entypo.eot new file mode 100644 index 0000000..41f223e Binary files /dev/null and b/app/public/fonts/entypo/entypo.eot differ diff --git a/app/public/fonts/entypo/entypo.svg b/app/public/fonts/entypo/entypo.svg new file mode 100644 index 0000000..86b3b30 --- /dev/null +++ b/app/public/fonts/entypo/entypo.svg @@ -0,0 +1,834 @@ + + + + +Created by FontForge 20110222 at Sun Nov 11 15:34:13 2012 + By Vitaly,,, +Copyright (C) 2012 by Daniel Bruce + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/public/fonts/entypo/entypo.ttf b/app/public/fonts/entypo/entypo.ttf new file mode 100644 index 0000000..331ea3a Binary files /dev/null and b/app/public/fonts/entypo/entypo.ttf differ diff --git a/app/public/fonts/entypo/entypo.woff b/app/public/fonts/entypo/entypo.woff new file mode 100644 index 0000000..b0771de Binary files /dev/null and b/app/public/fonts/entypo/entypo.woff differ diff --git a/app/public/imgs/.DS_Store b/app/public/imgs/.DS_Store new file mode 100644 index 0000000..bf07749 Binary files /dev/null and b/app/public/imgs/.DS_Store differ diff --git a/app/public/imgs/creationscreen/cs-django.png b/app/public/imgs/creationscreen/cs-django.png new file mode 100644 index 0000000..f436ff1 Binary files /dev/null and b/app/public/imgs/creationscreen/cs-django.png differ diff --git a/app/public/imgs/creationscreen/cs-html.png b/app/public/imgs/creationscreen/cs-html.png new file mode 100644 index 0000000..4933e57 Binary files /dev/null and b/app/public/imgs/creationscreen/cs-html.png differ diff --git a/app/public/imgs/creationscreen/cs-mongo.png b/app/public/imgs/creationscreen/cs-mongo.png new file mode 100644 index 0000000..984ed71 Binary files /dev/null and b/app/public/imgs/creationscreen/cs-mongo.png differ diff --git a/app/public/imgs/creationscreen/cs-node.png b/app/public/imgs/creationscreen/cs-node.png new file mode 100644 index 0000000..2db6b5f Binary files /dev/null and b/app/public/imgs/creationscreen/cs-node.png differ diff --git a/app/public/imgs/creationscreen/cs-none.png b/app/public/imgs/creationscreen/cs-none.png new file mode 100644 index 0000000..9c8b168 Binary files /dev/null and b/app/public/imgs/creationscreen/cs-none.png differ diff --git a/app/public/imgs/creationscreen/cs-other.png b/app/public/imgs/creationscreen/cs-other.png new file mode 100644 index 0000000..e3f89a0 Binary files /dev/null and b/app/public/imgs/creationscreen/cs-other.png differ diff --git a/app/public/imgs/creationscreen/cs-php.png b/app/public/imgs/creationscreen/cs-php.png new file mode 100644 index 0000000..0ad05bf Binary files /dev/null and b/app/public/imgs/creationscreen/cs-php.png differ diff --git a/app/public/imgs/creationscreen/cs-postgre.png b/app/public/imgs/creationscreen/cs-postgre.png new file mode 100644 index 0000000..b922a4b Binary files /dev/null and b/app/public/imgs/creationscreen/cs-postgre.png differ diff --git a/app/public/imgs/creationscreen/cs-python.png b/app/public/imgs/creationscreen/cs-python.png new file mode 100644 index 0000000..100098b Binary files /dev/null and b/app/public/imgs/creationscreen/cs-python.png differ diff --git a/app/public/imgs/creationscreen/cs-sql.png b/app/public/imgs/creationscreen/cs-sql.png new file mode 100644 index 0000000..1b140e3 Binary files /dev/null and b/app/public/imgs/creationscreen/cs-sql.png differ diff --git a/app/public/imgs/preloader.gif b/app/public/imgs/preloader.gif new file mode 100755 index 0000000..5337811 Binary files /dev/null and b/app/public/imgs/preloader.gif differ diff --git a/app/public/imgs/small_loader.gif b/app/public/imgs/small_loader.gif new file mode 100644 index 0000000..c5598fd Binary files /dev/null and b/app/public/imgs/small_loader.gif differ diff --git a/app/public/imgs/sprite-hdpi.png b/app/public/imgs/sprite-hdpi.png new file mode 100644 index 0000000..a5efe62 Binary files /dev/null and b/app/public/imgs/sprite-hdpi.png differ diff --git a/app/public/imgs/sprite-std.png b/app/public/imgs/sprite-std.png new file mode 100644 index 0000000..f409e4a Binary files /dev/null and b/app/public/imgs/sprite-std.png differ diff --git a/app/public/imgs/welcomescreen/sl-bg-2.jpg b/app/public/imgs/welcomescreen/sl-bg-2.jpg new file mode 100644 index 0000000..95c1afe Binary files /dev/null and b/app/public/imgs/welcomescreen/sl-bg-2.jpg differ diff --git a/app/public/themes/sprite.png b/app/public/themes/sprite.png new file mode 100644 index 0000000..04cb2a5 Binary files /dev/null and b/app/public/themes/sprite.png differ diff --git a/app/src/MainApp/client/app/Profile.js b/app/src/MainApp/client/app/Profile.js new file mode 100644 index 0000000..bdc045c --- /dev/null +++ b/app/src/MainApp/client/app/Profile.js @@ -0,0 +1,19 @@ +import React, { PropTypes, Component } from 'react'; +import Tracker from 'tracker-component'; +import { Accounts, STATES } from 'meteor/std:accounts-bootstrap'; +import { browserHistory } from 'react-router'; +import { Meteor } from 'meteor/meteor'; + + +export default class Profile extends Tracker.Component { + + + render() { + return ( +
+ +
+ ); + } + +} diff --git a/app/src/MainApp/client/app/Index.js b/app/src/MainApp/client/app/index.js similarity index 100% rename from app/src/MainApp/client/app/Index.js rename to app/src/MainApp/client/app/index.js diff --git a/app/src/MainApp/client/app/layouts/Footer.js b/app/src/MainApp/client/app/layouts/Footer.js index 1c408b5..07e7a6b 100644 --- a/app/src/MainApp/client/app/layouts/Footer.js +++ b/app/src/MainApp/client/app/layouts/Footer.js @@ -15,7 +15,7 @@ const AppFooter = () => ( {'\u00a0'} - Meteork Kit + Meteor Kit ); diff --git a/app/src/MainApp/client/index.js b/app/src/MainApp/client/index.js index d812ad9..a026151 100644 --- a/app/src/MainApp/client/index.js +++ b/app/src/MainApp/client/index.js @@ -13,7 +13,7 @@ Accounts.ui.config({ loginPath: '/signin', signUpPath: '/signup', resetPasswordPath: '/reset-password', - profilePath: '/', + profilePath: '/profile', minimumPasswordLength: 4, }); diff --git a/app/src/MainApp/client/routes.js b/app/src/MainApp/client/routes.js index b6552a3..a99e896 100644 --- a/app/src/MainApp/client/routes.js +++ b/app/src/MainApp/client/routes.js @@ -2,15 +2,16 @@ import { Route, IndexRoute } from 'react-router'; import { Meteor } from 'meteor/meteor'; import App from './app/App'; import Main from './app/Main'; -import Index from './app/Index'; +import Index from './app/index'; import NotFound from '../imports/ui/components/notfound/NotFoundPage'; import SignIn from '../imports/ui/components/auth/SignIn'; import SignUp from '../imports/ui/components/auth/SignUp'; import SignOut from '../imports/ui/components/auth/SignOut'; import Docs from '../imports/ui/components/docs/Docs'; import logger from 'cdm-logger'; +import Profile from 'Main/Profile'; -import { getRoutes } from '../../AdminApp/client/routes'; +import { getRoutes } from 'IDEApp/client/routes'; const checkAuth = to => (nextState, transition) => { if (!Meteor.loggingIn() && !Meteor.userId()) { @@ -28,7 +29,7 @@ class routes { * Only need to inject this on the CLIENT side for lazy loading */ injectStore(store) { - logger.debug('Injecting Store', store); + logger.debug('Injecting Store and available states are ', store.getState()); this.store = store; } @@ -52,6 +53,7 @@ class routes { + {/* -- Protected Site here --*/} diff --git a/app/src/MainApp/imports/api/graphql/resolvers/resolver.js b/app/src/MainApp/imports/api/graphql/resolvers/resolver.js index b9edc40..acbca0e 100644 --- a/app/src/MainApp/imports/api/graphql/resolvers/resolver.js +++ b/app/src/MainApp/imports/api/graphql/resolvers/resolver.js @@ -27,4 +27,5 @@ const resolvers = { }, }; + export default resolvers; diff --git a/app/src/MainApp/imports/api/graphql/schema/user.graphql b/app/src/MainApp/imports/api/graphql/schema/user.graphql index 0c22107..d1df324 100644 --- a/app/src/MainApp/imports/api/graphql/schema/user.graphql +++ b/app/src/MainApp/imports/api/graphql/schema/user.graphql @@ -10,5 +10,3 @@ type User { randomString: String _id: String } - - diff --git a/app/src/MainApp/server/index.js b/app/src/MainApp/server/index.js index 8ad6156..7b6062e 100644 --- a/app/src/MainApp/server/index.js +++ b/app/src/MainApp/server/index.js @@ -1 +1,9 @@ import './startup'; +import { Accounts } from 'meteor/accounts-base'; +import logger from 'cdm-logger' + +// Accounts.onCreateUser(function (options, user) { +// logger.debug("User", user); +// user.profile = options.profile || {username: user}; +// return user; +// }); \ No newline at end of file diff --git a/app/src/MainApp/server/lib/configureAccountsMeld.js b/app/src/MainApp/server/lib/configureAccountsMeld.js new file mode 100644 index 0000000..1b5aa36 --- /dev/null +++ b/app/src/MainApp/server/lib/configureAccountsMeld.js @@ -0,0 +1,13 @@ +import { Meteor } from 'meteor/meteor' +import { AccountsMeld } from 'meteor/splendido:accounts-meld' + + + +const configureAccountsMeld = () => { + AccountsMeld.configure({ + askBeforeMeld: true + }) +}; + + +export default configureAccountsMeld; \ No newline at end of file diff --git a/app/src/MainApp/server/startup/index.js b/app/src/MainApp/server/startup/index.js index 4a14a8e..19c6c1a 100644 --- a/app/src/MainApp/server/startup/index.js +++ b/app/src/MainApp/server/startup/index.js @@ -1,11 +1,14 @@ -import configureService from '../lib/configureService'; -import { Meteor } from 'meteor/meteor'; -import { BrowserPolicy } from 'meteor/browser-policy-common'; -import logger from 'cdm-logger'; - -const startup = () => { - logger.info('configuring login services'); - configureService(); +import { Meteor } from 'meteor/meteor' +import {BrowserPolicy} from 'meteor/browser-policy-common' +import configureService from '../lib/configureService' +import configureAccountsMeld from '../lib/configureAccountsMeld' +import logger from 'cdm-logger' + +let startup = () => { + logger.info("configuring login services"); + configureService(); + logger.info("configuring account meld"); + configureAccountsMeld(); }; if (Meteor.isServer && process.env.NODE_ENV === 'development') { diff --git a/app/src/common/configureApollo.js b/app/src/common/configureApollo.js index 958c1f9..c0a8df5 100644 --- a/app/src/common/configureApollo.js +++ b/app/src/common/configureApollo.js @@ -1,7 +1,37 @@ import ApolloClient, { createNetworkInterface } from 'apollo-client'; - +<<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 4dbaabf... fixed SSR +import { meteorClientConfig } from 'meteor/apollo'; + + +// let url; +// const opts = {}; +// if (Meteor.isServer) { +// opts.ssrMode = true; +// url = `http://${config.host}:${config.port}/graphql`; +// } else { +// opts.ssrForceFetchDelay = 100; +// url = '/graphql'; +// } + +const opts = {}; +if (Meteor.isServer) { + opts.ssrMode = true; +} else { + opts.ssrForceFetchDelay = 100; +} +<<<<<<< HEAD +======= import { meteorClientConfig } from 'meteor/apollo'; - +<<<<<<< HEAD +>>>>>>> fe75b6f... with apollo subscription +======= +import { RxApolloClient } from 'apollo-client-rxjs'; +>>>>>>> e6aac71... changed to use graphql +======= +>>>>>>> 4dbaabf... fixed SSR // export const configureApolloClient = (headers = {}, url = '/graphql', options = {}) => new ApolloClient({ // networkInterface: createNetworkInterface({ @@ -15,7 +45,17 @@ import { meteorClientConfig } from 'meteor/apollo'; // }); +<<<<<<< HEAD +<<<<<<< HEAD +export const createClient = () => new ApolloClient(meteorClientConfig(opts)); +======= +export const createClient = () => { -export const createClient = () => new ApolloClient(meteorClientConfig()); + return new ApolloClient(meteorClientConfig()); +} +>>>>>>> fe75b6f... with apollo subscription +======= +export const createClient = () => new ApolloClient(meteorClientConfig(opts)); +>>>>>>> 4dbaabf... fixed SSR diff --git a/app/src/common/configureDeps.js b/app/src/common/configureDeps.js index 92aa533..be3d2e1 100644 --- a/app/src/common/configureDeps.js +++ b/app/src/common/configureDeps.js @@ -13,7 +13,7 @@ import validate from './validate'; const configureDeps = (initialState, platformDeps) => ({ ...platformDeps, - getUid: () => platformDeps.uuid.v4(), + getUid: () => platformDeps.uuid.id(), now: () => Date.now(), validate, }); diff --git a/app/src/common/configureEpics.js b/app/src/common/configureEpics.js index 457646d..ff9fb5f 100644 --- a/app/src/common/configureEpics.js +++ b/app/src/common/configureEpics.js @@ -1,6 +1,7 @@ /* @flow weak */ import 'rxjs'; import { combineEpics } from 'redux-observable'; +import { BehaviorSubject } from 'rxjs/BehaviorSubject'; import { epics as appEpics } from './app/actions'; /* @@ -10,7 +11,17 @@ const epics = [ ...appEpics, ]; +const epic$ = new BehaviorSubject(combineEpics(...epics)); + const configureEpics = (deps: Object) => (action$, { getState }) => - combineEpics(...epics)(action$, { ...deps, getState }); + epic$.mergeMap(epic => epic(action$, { ...deps, getState })); + +export const registerEpic = (epic) => { + // don't add an epic that is already registered/running + if (epics.indexOf(epic) === -1) { + epics.push(epic); + epic$.next(epic); + } +}; export default configureEpics; diff --git a/app/src/common/configureMiddleware.js b/app/src/common/configureMiddleware.js index e7f95f8..c9b4f8a 100644 --- a/app/src/common/configureMiddleware.js +++ b/app/src/common/configureMiddleware.js @@ -20,10 +20,13 @@ const configureMiddleware = (initialState, platformDeps, platformMiddleware) => const deps = configureDeps(initialState, platformDeps); const rootEpic = configureEpics(deps); const epicMiddleware = createEpicMiddleware(rootEpic); + const { apolloClient } = platformDeps; + const apolloMiddleware = apolloClient.middleware(); const middleware = [ injectMiddleware(deps), epicMiddleware, + apolloMiddleware, ...platformMiddleware, ]; diff --git a/app/src/common/configureReducer.js b/app/src/common/configureReducer.js index 55befa7..b4d0a67 100644 --- a/app/src/common/configureReducer.js +++ b/app/src/common/configureReducer.js @@ -9,13 +9,14 @@ import todos from './todos/reducer'; import { combineReducers } from 'redux'; import { routerReducer as routing } from 'react-router-redux'; import { fieldsReducer as fields } from './lib/redux-fields'; - +import logger from 'cdm-logger'; /* users and auth are removed from original version routerReducer is also used which don't exist in original version injectReducer is custom one added for asyncReducers Added custom changes + Added apollo to resetStateOnSignOutReducer */ // stackoverflow.com/q/35622588/233902 @@ -39,11 +40,20 @@ const resetStateOnSignOutReducer = (reducer, initialState) => ( config: initialState.config, device: initialState.device, intl: initialState.intl, +<<<<<<< HEAD +<<<<<<< HEAD + routing: state.routing, // Routing state has to be reused +======= routing: state.routing, // Routing sstate has to be reused +>>>>>>> fe75b6f... with apollo subscription +======= + routing: state.routing, // Routing state has to be reused +>>>>>>> 4dbaabf... fixed SSR + apollo: state.apollo, }, action); }; -const configureReducer = (initialState: Object, asyncReducers) => { +const configureReducer = (initialState: Object, asyncReducers: Object) => { let reducer = combineReducers({ app, config, @@ -62,7 +72,11 @@ const configureReducer = (initialState: Object, asyncReducers) => { return reducer; }; -export const injectReducer = (store, reducers) => { +export const injectReducer = (store: Object, reducers: Object) => { + if (!store) { + logger.warn('Injecting reducer when store is null'); + return; + } store.asyncReducers = { ...store.asyncReducers, ...reducers }; store.replaceReducer(configureReducer(store.getState(), store.asyncReducers)); }; diff --git a/app/src/common/configureStore.js b/app/src/common/configureStore.js index fd63881..2b69eb6 100644 --- a/app/src/common/configureStore.js +++ b/app/src/common/configureStore.js @@ -4,6 +4,7 @@ import configureReducer from './configureReducer'; import configureStorage from './configureStorage'; import { applyMiddleware, createStore, compose } from 'redux'; import { routerMiddleware } from 'react-router-redux'; +import { Meteor } from 'meteor/meteor'; import { persistStore, autoRehydrate } from 'redux-persist'; import logger from 'cdm-logger'; @@ -22,7 +23,15 @@ const configureStore = (options: Options) => { platformDeps = {}, platformMiddleware = [], } = options; - const reducer = configureReducer(initialState); +<<<<<<< HEAD +<<<<<<< HEAD + const asyncReducers = { apollo: platformDeps.apolloClient.reducer() }; +======= +>>>>>>> fe75b6f... with apollo subscription +======= + const asyncReducers = { apollo: platformDeps.apolloClient.reducer() }; +>>>>>>> 4dbaabf... fixed SSR + const reducer = configureReducer(initialState, asyncReducers); // ====================================================== // Middleware Configuration @@ -44,7 +53,6 @@ const configureStore = (options: Options) => { } } - const store = createStore( reducer, initialState, @@ -65,7 +73,7 @@ const configureStore = (options: Options) => { } // to inject reducers in future - store.asyncReducers = {}; + store.asyncReducers = { ...asyncReducers }; // Enable hot reloading for reducers. @@ -76,14 +84,14 @@ const configureStore = (options: Options) => { module.hot.accept(() => { const configureReducer = require('./configureReducer'); - store.replaceReducer(configureReducer(initialState)); + store.replaceReducer(configureReducer(initialState, asyncReducers)); }); } else { // Webpack for some reason needs accept with the explicit path. module.hot.accept('./configureReducer', () => { const configureReducer = require('./configureReducer'); - store.replaceReducer(configureReducer(initialState)); + store.replaceReducer(configureReducer(initialState, asyncReducers)); }); } } diff --git a/app/src/graphql/models.js b/app/src/graphql/models.js new file mode 100644 index 0000000..ed42f9c --- /dev/null +++ b/app/src/graphql/models.js @@ -0,0 +1,5 @@ +import { models as ideModels } from '../IDEApp/imports/api/graphql/connectors/models'; +import { merge } from 'lodash'; + + +export default merge(ideModels); diff --git a/app/src/graphql/schema.js b/app/src/graphql/schema.js new file mode 100644 index 0000000..632f962 --- /dev/null +++ b/app/src/graphql/schema.js @@ -0,0 +1,33 @@ +import { makeExecutableSchema, addMockFunctionsToSchema, addResolveFunctionsToSchema } from 'graphql-tools'; +import logger from 'cdm-logger'; +import { merge } from 'lodash'; +import defaultResolvers from '../MainApp/imports/api/graphql/resolvers/resolver'; +import ideResolvers from '../IDEApp/imports/api/graphql/resolvers/'; +import loader from 'graphql-schema-collector'; + + +const clientLogger = { log: Meteor.bindEnvironment(e => logger.error(e.stack)) }; +// Load graphql schema and resolvers. Schemas are automatically loaded +// Resolvers must be manually loaded by adding the import +let schemaString; +try { + schemaString = loader.loadSchema.sync(`${process.env.PWD}/src/**/schema/*.graphql`); + logger.debug('Graphql query loaded!', schemaString); +} catch (err) { + logger.error('Schema Load failure:', err); +} +const resolvers = merge(defaultResolvers, ideResolvers); + +const executableSchema = makeExecutableSchema({ + typeDefs: [schemaString], + resolvers, + logger: clientLogger, + allowUndefinedInResolve: true, // optional + resolverValidationOptions: { + requireResolversForNonNull: true, + requireResolversForArgs: true, + rejectExtraResolvers: true, + }, // optional +}); + +export default executableSchema; diff --git a/app/src/graphql/subscriptions.js b/app/src/graphql/subscriptions.js new file mode 100644 index 0000000..1f312e7 --- /dev/null +++ b/app/src/graphql/subscriptions.js @@ -0,0 +1,15 @@ +import { PubSub, SubscriptionManager } from 'graphql-subscriptions'; +import schema from './schema'; +import logger from 'cdm-logger'; +import * as subscriptions from '../IDEApp/imports/api/graphql/subscriptions'; + +const pubsub = new PubSub(); +const subscriptionManager = new SubscriptionManager({ + schema, + pubsub, + setupFuctions: { + ...subscriptions, + }, +}); + +export { subscriptionManager, pubsub }; diff --git a/app/src/routes.js b/app/src/routes.js index 0cd26a2..0341616 100644 --- a/app/src/routes.js +++ b/app/src/routes.js @@ -1,7 +1,9 @@ import { ReactRouterSSR } from 'meteor/reactrouter:react-router-ssr'; import { syncHistoryWithStore } from 'react-router-redux'; import { Provider } from 'react-redux'; +import { merge } from 'lodash'; import ReactHelmet from 'react-helmet'; +import ReactCookie from 'react-cookie'; import Routes from './MainApp/client/routes'; import configureStore from './common/configureStore'; import createInitialState from './MainApp/imports/config/createInitialState'; @@ -10,53 +12,69 @@ import localforage from 'localforage'; import { Random } from 'meteor/random'; import config from './MainApp/imports/config/config'; import ReactGA from 'react-ga'; +import { Meteor } from 'meteor/meteor'; import { ApolloProvider, getDataFromTree } from 'react-apollo'; -import { injectReducer } from './common/configureReducer'; import { createClient } from './common/configureApollo'; -let url; -const opts = {}; -if (Meteor.isServer) { - opts.ssrMode = true; - url = `http://${config.host}:${config.port}/graphql`; -} else { - opts.ssrForceFetchDelay = 100; - url = '/graphql'; -} +let initialReduxState; - -let client; -let headers; +<<<<<<< HEAD +<<<<<<< HEAD +<<<<<<< HEAD +======= +======= +// client = createClient(url, opts); +>>>>>>> e6aac71... changed to use graphql +const client = createClient(); // createInitialState loads files, so it must be called once. let initialState = createInitialState(); +>>>>>>> fe75b6f... with apollo subscription +======= +>>>>>>> 4dbaabf... fixed SSR let history; -let configureReporting; +let store; const routes = new Routes(); -const reportingMiddleware = () => configureReporting({ - appVersion: initialState.config.appVersion, - sentryUrl: initialState.config.sentryUrl, - unhandledRejection: fn => window.addEventListener('unhandledrejection', fn), -}); const getLocale = req => process.env.IS_SERVERLESS ? config.defaultLocale : req.acceptsLanguages(config.locales) || config.defaultLocale; // TODO: need to get the locale from browser -const getStore = () => { + +const getStore = (initialState, client) => { if (Meteor.isClient) { - configureReporting = require('./common/configureReporting'); - logger.debug('Configuring store at client side.'); + const configureReporting = require('./common/configureReporting'); + + const reportingMiddleware = configureReporting({ + appVersion: initialState.config.appVersion, + sentryUrl: initialState.config.sentryUrl, + unhandledRejection: fn => window.addEventListener('unhandledrejection', fn), + }); + return configureStore({ initialState, - platformDeps: { uuid: Random, storageEngine: localforage }, - platformMiddleware: [reportingMiddleware()], +<<<<<<< HEAD +<<<<<<< HEAD + platformDeps: { uuid: Random, storageEngine: localforage, apolloClient: client }, + platformMiddleware: [reportingMiddleware], +======= + extraArguments: client, + asyncReducers: { apollo: client.reducer() }, + platformDeps: { uuid: Random, storageEngine: localforage, apolloClient: client }, + platformMiddleware: [client.middleware(), reportingMiddleware()], +>>>>>>> fe75b6f... with apollo subscription +======= + platformDeps: { uuid: Random, storageEngine: localforage, apolloClient: client }, + platformMiddleware: [reportingMiddleware], +>>>>>>> 4dbaabf... fixed SSR }); } + + // this should run on server (SSR) return configureStore({ initialState: { ...initialState, @@ -68,45 +86,45 @@ const getStore = () => { currentLocale: 'en', initialNow: Date.now(), }, - } }); + }, + platformDeps: { apolloClient: client }, + }); }; -const store = getStore(); - - // Create an enhanced history that syncs navigation events with the store +<<<<<<< HEAD +<<<<<<< HEAD +const historyHook = newHistory => history = newHistory; +======= const historyHook = (newHistory) => { - history = syncHistoryWithStore(newHistory, store); + // history = syncHistoryWithStore(newHistory, store); // Setup Google Analytics page tracking - if (config.isProduction && Meteor.isClient && config.googleAnalyticsId !== 'UA-XXXXXXX-X') { - ReactGA.initialize(config.googleAnalyticsId); - history.listen((location) => { - ReactGA.set({ page: location.pathname }); - ReactGA.pageview(location.pathname); - }); - } + // if (config.isProduction && Meteor.isClient && config.googleAnalyticsId !== 'UA-XXXXXXX-X') { + // ReactGA.initialize(config.googleAnalyticsId); + // history.listen((location) => { + // ReactGA.set({ page: location.pathname }); + // ReactGA.pageview(location.pathname); + // }); + // } + history = newHistory; return history; }; +>>>>>>> 4dbaabf... fixed SSR +======= +const historyHook = newHistory => history = newHistory; +>>>>>>> 0f9faf8... to fix loading props in wrapperHook // Pass the state of the store as the object to be dehydrated server side -const dehydrateHook = () => Object.assign({}, - store.getState(), - { - apollo: { - data: store.getState().apollo.data, - }, - }, - -); +const dehydrateHook = () => store.getState(); // Take the rehydrated state and use it as initial state client side const rehydrateHook = (state) => { + logger.debug('Rehydrate state from server state.', state); if (state) { - logger.debug('Rehydrate state from server state.'); - initialState = state; + initialReduxState = state; return state; } return null; @@ -126,15 +144,55 @@ const clientProps = { // Create a redux store and pass into the redux Provider wrapper const wrapperHook = (app) => { + const client = createClient(); + store = getStore(initialReduxState || createInitialState(), client); routes.injectStore(store); - client = createClient(url, opts); - injectReducer(store, { apollo: client.reducer() }); +<<<<<<< HEAD +<<<<<<< HEAD +<<<<<<< HEAD +======= +>>>>>>> 0f9faf8... to fix loading props in wrapperHook + history = syncHistoryWithStore(history, store); + if (Meteor.isClient) { + // Setup Google Analytics page tracking + if (config.isProduction && config.googleAnalyticsId !== 'UA-XXXXXXX-X') { + ReactGA.initialize(config.googleAnalyticsId); + history.listen((location) => { + ReactGA.set({ page: location.pathname }); + ReactGA.pageview(location.pathname); + }); + } + } + + return ({app({ history })}); +<<<<<<< HEAD +======= +// client = createClient(url, opts); +// injectReducer(store, { apollo: client.reducer() }); + logger.debug("WrapperHook", store); +======= +>>>>>>> e6aac71... changed to use graphql return ({app}); +>>>>>>> fe75b6f... with apollo subscription +======= +>>>>>>> 0f9faf8... to fix loading props in wrapperHook }; // the preRender: Executed just before the renderToString -const preRender = (req, res) => (headers = req.headers); +const preRender = (req, res) => { +<<<<<<< HEAD +<<<<<<< HEAD + ReactCookie.plugToRequest(req, res); +======= + // const locale = getLocale(req); + // logger.debug("logging local", locale); +>>>>>>> 4dbaabf... fixed SSR +======= + ReactCookie.plugToRequest(req, res); +>>>>>>> 0f9faf8... to fix loading props in wrapperHook +}; +const dataLoader = async (req, res, app) => await (getDataFromTree(app)); const clientOptions = { props: clientProps, @@ -147,6 +205,7 @@ const serverOptions = { historyHook, dehydrateHook, preRender, + dataLoader, htmlHook, }; diff --git a/app/src/server.js b/app/src/server.js index b5c11ea..f91efe7 100644 --- a/app/src/server.js +++ b/app/src/server.js @@ -1,12 +1,22 @@ import { ReactRouterSSR } from 'meteor/reactrouter:react-router-ssr'; import 'MainApp/server'; +import 'IDEApp/server'; import { createApolloServer } from 'meteor/apollo'; -import { makeExecutableSchema, addMockFunctionsToSchema } from 'graphql-tools'; - -import cdmLogger from 'cdm-logger'; -import resolvers from './MainApp/imports/api/graphql/resolvers/resolver'; -import loader from 'graphql-schema-collector'; - +<<<<<<< HEAD +<<<<<<< HEAD +import schema from './graphql/schema'; +import { subscriptionManager } from './graphql/subscriptions'; +import models from './graphql/models'; +======= +import schema from './schema'; +import { subscriptionManager } from './subscriptions'; +>>>>>>> fe75b6f... with apollo subscription +======= +import schema from './graphql/schema'; +import { subscriptionManager } from './graphql/subscriptions'; +import models from './graphql/models'; +>>>>>>> e6aac71... changed to use graphql +import logger from 'cdm-logger'; // Do server-rendering only in production // Otherwise, it will break the hot-reload @@ -18,20 +28,14 @@ if (process.env.NODE_ENV === 'production') { require('./routes').default; } -const logger = { log: Meteor.bindEnvironment(e => cdmLogger.error(e.stack)) }; -// Load graphql schema and resolvers. Schemas are automatically loaded -// Resolvers must be manually loaded by adding the import -loader.loadSchema(`${process.env.PWD}/src/**/schema/*.graphql`, (err, schema) => { - if (err) { - cdmLogger.error(err); - return; - } - cdmLogger.debug('Graphql query loaded!', schema); - createApolloServer({ - schema: makeExecutableSchema({ - typeDefs: [schema], - resolvers, - logger, - }), - }); -}); +createApolloServer({ + schema, +<<<<<<< HEAD +<<<<<<< HEAD + context: models, +======= +>>>>>>> fe75b6f... with apollo subscription +======= + context: models, +>>>>>>> e6aac71... changed to use graphql +}, { subscriptionManager }); diff --git a/app/webpack.json b/app/webpack.json index e3090c0..2904601 100644 --- a/app/webpack.json +++ b/app/webpack.json @@ -28,5 +28,5 @@ "react/lib/ReactCSSTransitionGroup": "React.addons.CSSTransitionGroup", "graphql": "graphql" }, - "noParse": ["node_modules/localforage/dist/localforage.js"] + "noParse": ["node_modules/localforage/dist/localforage.js", "node_modules/xterm/dist/xterm.js"] } diff --git a/config/development/.gitignore b/config/development/.gitignore index e69de29..84c63ce 100644 --- a/config/development/.gitignore +++ b/config/development/.gitignore @@ -0,0 +1,2 @@ +settings.json +env.sh diff --git a/config/development/settings.json b/config/development/settings.json index 9529f69..8d71bcd 100644 --- a/config/development/settings.json +++ b/config/development/settings.json @@ -1,10 +1,21 @@ { + "MONGO_URL": "mongodb://localhost:3001/meteor", "public": { "sentryUrl": "https://0121f514fb4141eb8377845fb686d266@app.getsentry.com/90886", "googleAnalyticsId": "UA-XXXXXXX-X", + "io": "http://localhost:4000/bridge", "logLevel": "debug" }, "private": { - + "oAuth": { + "github": { + "clientId": "b723f6f3285e6c3d7ee7", + "secret": "a1a3cee0f077e2dff69b11c67d42ac0ed827ae3c" + }, + "linkedin": { + "clientId": "78phbs7zohrfxk", + "secret": "3fJLgqUSf7l2aW7J" + } + } } }