Skip to content

Commit

Permalink
v0.1.13 (#61)
Browse files Browse the repository at this point in the history
* initial commit

* change to v-slot

* improve on nuxt dynamic route handling

* mongodb watch wip

* add mongo to firebase example, rename project from example-firebase to example-baas

* update packages

* restructure example files, update docs and build

* update README.md
  • Loading branch information
ais-one committed Jun 20, 2019
1 parent 654b0da commit 5fda3b5
Show file tree
Hide file tree
Showing 80 changed files with 550 additions and 346 deletions.
37 changes: 23 additions & 14 deletions README.md
@@ -1,24 +1,32 @@
[![npm version](https://badge.fury.io/js/vue-crud-x.svg)](https://badge.fury.io/js/vue-crud-x) [![npm](https://img.shields.io/npm/dm/vue-crud-x.svg)](https://www.npmjs.com/package/vue-crud-x) [![MadeWithVueJs.com shield](https://madewithvuejs.com/storage/repo-shields/823-shield.svg)](https://madewithvuejs.com/p/vue-crud-x/shield-link)

## QUICKSTART

The **example-rest** folder is the preferred project for quickstart. Everything (frontend and sample REST backend) runs locally.

The **example-nuxt** folder contains example using NuxtJS, a VueJS framework. Two demos are possible SSR and Static Generated Pages. This example also includes Github social login (you need to setup Github make this work)

# NOTICES & UPDATES

> Latest Version 0.1.12 Released 2019 May 25 1630 +8GMT
> Latest Version 0.1.13 Released 2019 Jun 20 0815 +8GMT
**Our next release, we will migrate to Vuetify 2.0...** There may be breaking changes as the new **v-data-table** component has more slot handling and features. We will take this chance to improve the framework while minimizing the effect of breaking changes

Roadmap and latest updates can be found on the <a href="https://github.com/ais-one/vue-crud-x/wiki" target="_blank">Wiki</a>.

See RELEASE.MD file for change history.

Read the following <a href="https://medium.com/@aaronjxz/vue-crud-x-a-highly-customisable-crud-component-using-vuejs-and-vuetify-2b1539ce2054" target="_blank">supporting article</a> (with usage and explanations updated as and when required)


## 0 QUICKSTART

- **example-rest** folder is preferred project for quickstart. Everything runs locally.
- **example-nuxt** folder uses NuxtJS (SSR and generate demo), Also includes Github login


## 1 New Features

1. More Apollo Client GraphQL features cache, optimistic response, refetch queries
- Rename example-firebase to example-baas and added Mongo Stitch login and query example
- Setting up Mongo Stitch https://docs.mongodb.com/stitch/tutorials/guides/todo-backend/
- Setup email and password authorization provider instead of anonymous provider
- Improved Nuxt page error handling using error layout page
- Vue 3 migration: updated slots to use v-slot


## 2 Major Improvements (Without Breaking Changes)

Expand All @@ -31,8 +39,8 @@ Usage example can be found:
- example-rest/src/components/author.js
- example-rest/src/pages/Category.vue
- in **example-nuxt** project (see example-nuxt/README.md on quickstart)
- in **example-firebase** project
- example-firebase/src/pages/MultiCrud/Example.vue (also, demonstrates multiple vue-crud-x used in a single page)
- in **example-baas** project
- example-baas/src/pages/MultiCrud/Example.vue (also, demonstrates multiple vue-crud-x used in a single page)

---

Expand All @@ -59,7 +67,7 @@ Our examples showcase the following (unrelated to the vue-crud-x features above)
- rxJs for cleaner code (auto-complete, debounce, fetch latest)
- 2FA OTP signin with Google Authenticator (setup with USE_OTP=GA in environement files of both the front and backend. Check DB seeders for the API key to use, or you can find out how to generate your own)
- websocket example
- graphql example
- graphql example (use Apollo client: authentication, subscriptions, cache, optimistic response, refetch queries)
- https://github.com/ais-one/vue-crud-x/tree/master/example-rest
- in **example-nuxt**
- includes features in example-rest plus the following:
Expand All @@ -68,20 +76,21 @@ Our examples showcase the following (unrelated to the vue-crud-x features above)
- SSR App
- pre-generated Static Web App
- https://github.com/ais-one/vue-crud-x/tree/master/example-nuxt
- in **example-firebase**
- in **example-baas**
- Serverless backend, using Firebase backend-as-a-service, need to register and setup
- real-time updates from Firestore
- Use multiple vue-crud-x in single page
- recaptcha, image capture from webcam
- https://github.com/ais-one/vue-crud-x/tree/master/example-firebase
- image upload to Google Cloud Store, Image capture via webcam
- include Mongo Stitch Baas login and simple query example
- https://github.com/ais-one/vue-crud-x/tree/master/example-baas

The **backend** project is an Express server used by **example-rest** and **example-nuxt** projects for testing the vue-crud-x component, and has the following features:
- ObjectionJS + SQLite (Sample SQL DB with 1-1, 1-m, m-n use cases, transactions, migrations, seeders, OpenAPI documentation), Mongo (connect test only)
- Login, JWT & 2FA OTP (using Google Authenticator)
- Key-Value Store for user token storage on server (can replace with redis)
- Websocket (use https://www.websocket.org/echo.html & ngrok to test)
- GraphQL
- GraphQL (use Apollo server)
- https://github.com/ais-one/vue-crud-x/tree/master/backend


Expand Down
27 changes: 19 additions & 8 deletions RELEASE.md
@@ -1,13 +1,6 @@
### Upcoming
* RESTful++ Backend For Testing
* Non-essential items
* Multiple File upload example (to local folder)
* Single File upload example (to firebase storage)
* Logging
* Security Improvements
* Automated testing (dredd.io)
* VueJS 3.0 update
* Vuetify 2.0 breaking changes list - check to see which will affect the code base
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-beta.0
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-alpha.18
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-alpha.13
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-alpha.12
Expand All @@ -18,6 +11,14 @@
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-alpha.7
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-alpha.5
* https://github.com/vuetifyjs/vuetify/releases/tag/v2.0.0-alpha.4
* RESTful++ Backend For Testing
* Non-essential items
* Multiple File upload example (to local folder)
* Single File upload example (to firebase storage)
* Logging
* Security Improvements
* Automated testing (dredd.io)
* VueJS 3.0 update
* improve i18n
* https://github.com/ais-one/vue-crud-x/issues/32
* https://github.com/vuetifyjs/vuetify/pull/5232
Expand All @@ -35,6 +36,16 @@
* v0.1.4 - CRUD operations to return object instead of number
* v0.1.3 - use 'field' instead of 'type' for Form and Filter inputs

### Version 0.1.13 - Our Last Update Before Vuetify 2.0 update
* rename example-firebase folder to example-baas
* add mongo stitch to example-baas
* nuxt: add error loayout, handle dynamic route error on static pages
* vue3: https://github.com/vuejs/rfcs/blob/master/active-rfcs/0001-new-slot-syntax.md
* improvement: backend, add testing?
* chore: clean up and improve code when possible, bug fixes
* chore: package updates
* chore: monitor VuetifyJS 2 & VueJS 3 updates, start migration from beta release onwards

### Version 0.1.12
* improvement: apollo graphql features (optimistic UI, refetch queries, cache)
* chore: add formReload flag to VueCrudX (default true), as original REST API always reloads after CRUD. We set it to false (see Categories.vue page), as graphql has optimistic UI, cache and refetch queries available and we make use of them instead for this case.
Expand Down
11 changes: 3 additions & 8 deletions backend/index.js
Expand Up @@ -42,12 +42,10 @@ apollo.applyMiddleware({ app }); // console.log(`GraphqlPATH ${server.graphqlPat
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: true }))

app.use(history())
app.use(history()) // causes problems when using postman, comment out to checkout API
app.use(express.static('public')) // for html content
app.use('/api-docs', express.static('docs'), swaggerUi.serve, swaggerUi.setup(swaggerDocument, { // for OpenAPI
swaggerOptions: {
docExpansion: 'none'
},
swaggerOptions: { docExpansion: 'none' },
explorer: true
}))

Expand All @@ -61,10 +59,7 @@ const apiRoutes = require('./routes/api')
app.use(cors())
app.use('/api/auth', authRoutes)
app.use('/api', apiRoutes)

app.get("*", async (req, res) => {
return res.status(404).json({ data: 'Not Found...' })
})
app.get("*", async (req, res) => res.status(404).json({ data: 'Not Found...' }))

// for Firebase Functions
// exports.api = functions.https.onRequest(async (req, res) => {
Expand Down
24 changes: 12 additions & 12 deletions backend/package.json
Expand Up @@ -19,8 +19,8 @@
},
"dependencies": {
"@keyv/redis": "^1.3.8",
"apollo-server-express": "^2.5.0",
"axios": "^0.18.0",
"apollo-server-express": "^2.6.3",
"axios": "^0.18.1",
"bcryptjs": "^2.4.3",
"body-parser": "^1.19.0",
"connect-history-api-fallback": "^1.6.0",
Expand All @@ -29,27 +29,27 @@
"date-fns": "^1.29.0",
"del": "^4.1.1",
"dotenv": "^8.0.0",
"express": "^4.17.0",
"firebase-admin": "^8.0.0",
"express": "^4.17.1",
"firebase-admin": "^8.2.0",
"graphql": "^14.3.1",
"influx": "^5.0.7",
"ioredis": "^4.9.5",
"influx": "^5.1.1",
"ioredis": "^4.10.0",
"jsonwebtoken": "^8.5.1",
"keyv": "^3.1.0",
"knex": "^0.16.5",
"mongodb": "^3.2.6",
"knex": "^0.17.6",
"mongodb": "^3.2.7",
"morgan": "^1.9.1",
"multer": "^1.4.1",
"mysql": "^2.17.1",
"objection": "^1.6.9",
"otplib": "^11.0.0",
"otplib": "^11.0.1",
"qrcode": "^1.3.3",
"sqlite3": "^4.0.8",
"sqlite3": "^4.0.9",
"swagger-jsdoc": "^3.2.9",
"swagger-ui-express": "^4.0.4",
"swagger-ui-express": "^4.0.6",
"uuid": "^3.3.2",
"winston": "^3.2.1",
"ws": "^7.0.0",
"ws": "^7.0.1",
"yamljs": "^0.3.0"
},
"devDependencies": {
Expand Down
5 changes: 2 additions & 3 deletions backend/routes/api.js
Expand Up @@ -13,14 +13,13 @@ const mongo = require('../services/mongo')
const UPLOAD_PATH = 'uploads/'
const upload = multer({ dest: `${UPLOAD_PATH}` }) // multer configuration


const { transaction } = require('objection')
const knex = Book.knex() // You can access `knex` instance anywhere you want. One way is to get it through any model.

apiRoutes
.get('/test', async (req,res) => {
.get('/', async (req,res) => {
try {
results = mongo ? await mongo.db().collection('users').find({}).toArray() : []
results = mongo ? await mongo.db().collection('exchangeUsers').find({}).toArray() : []
console.log(results)
} catch (e) {
console.log(e)
Expand Down
122 changes: 120 additions & 2 deletions backend/services/mongo.js
@@ -1,6 +1,76 @@
// const ObjectID = require('mongodb').ObjectID
let mongo

// reconnection
// does happen, to test out. shutdown mongo server, wait awhile then start up. CRUD will take effect and updates will take effect also...

// watch changes
// in mongo client, run rs.initiate() - but how to start mongo rs without calling this command?
// .\bin\mongod.exe --dbpath .\bin\data --port 27017 --replSet rs0

/*
// replace
{
_id: {
_data: '825D07B9C7000000012B022C0100296E5A10046D79825AAFE447EE93D29D46B0D1AF5846645F696400645CE20EDD520C352CBCF453E80004'
},
operationType: 'replace',
clusterTime: Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1560787399 },
fullDocument: {
_id: 5ce20edd520c352cbcf453e8,
username: 'user5a',
email: 'user5',
clientId: '5c9b1eb8cb3521eccb35431b',
password: '$2a$12$1K.MWGt6Ez30WJ05mYAK6u/dvjoce0O.IATL2TYxLGxCv2rju9ccS',
gaKey: 'IZDXCUDYNQ4ESMZZNY4HGZSDJRAVGZCO',
sms: '',
smsLastSent: null,
smsOtpPin: '',
smsVerified: 0,
telegramId: '',
telegramUsername: '',
role: 'user'
},
ns: { db: 'mm', coll: 'exchangeUsers' },
documentKey: { _id: 5ce20edd520c352cbcf453e8 }
}
// insert
{ _id:
{ _data:
'825D07BBBC000000012B022C0100296E5A10046D79825AAFE447EE93D29D46B0D1AF5846645F696400645D07BBBCCAABD31DCDB648950004' },
operationType: 'insert',
clusterTime:
Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1560787900 },
fullDocument:
{ _id: 5d07bbbccaabd31dcdb64895,
username: 'user6aa',
email: 'user6aa',
clientId: '5c9b1eb8cb3521eccb35431b',
password:
'$2a$12$1K.MWGt6Ez30WJ05mYAK6u/dvjoce0O.IATL2TYxLGxCv2rju9ccS',
gaKey: 'IZDXCUDYNQ4ESMZZNY4HGZSDJRAVGZCO',
sms: '',
smsLastSent: null,
smsOtpPin: '',
smsVerified: 0,
telegramId: '',
telegramUsername: '',
role: 'user' },
ns: { db: 'mm', coll: 'exchangeUsers' },
documentKey: { _id: 5d07bbbccaabd31dcdb64895 } }
// delete
{ _id:
{ _data:
'825D07BBEF000000012B022C0100296E5A10046D79825AAFE447EE93D29D46B0D1AF5846645F696400645D07BBBCCAABD31DCDB648950004' },
operationType: 'delete',
clusterTime:
Timestamp { _bsontype: 'Timestamp', low_: 1, high_: 1560787951 },
ns: { db: 'mm', coll: 'exchangeUsers' },
documentKey: { _id: 5d07bbbccaabd31dcdb64895 } }
*/
let mongo
let mongoStream
console.log('MONGO_URL', process.env.MONGO_URL) // TBD: if undefined?

if (!mongo && process.env.MONGO_URL) {
Expand All @@ -18,7 +88,17 @@ if (!mongo && process.env.MONGO_URL) {
// reconnectInterval
})
// try { await mongo.connect() } catch (e) { }
mongo.connect(function (err) { if (err) console.log('mongo error', err) })
mongo.connect((err, db) => {
if (err) console.log('mongo error', err)
else if (db) {
mongoStream = db.db('mm').collection('exchangeUsers').watch()
// db.db.collection('exchangeUsers').watch()
mongoStream.on('change', (change) => {
console.log(change); // You could parse out the needed info and send only that data.
// use websocket to listen to changes
})
}
})
// })()
} catch (e) { console.log('mongo', e) }
}
Expand All @@ -28,3 +108,41 @@ module.exports = mongo
// mongo,
// ObjectID: require('mongodb').ObjectID
// }


/*
const mongo = require("mongodb").MongoClient;
mongo.connect("mongodb://localhost:27017/?replicaSet=rs0").then(client => {
console.log("Connected to MongoDB server");
// Select DB and Collection
const db = client.db("mydb");
const collection = db.collection("Stocks");
pipeline = [
{
$match: { "fullDocument.price": { $gte: 250 } }
}
];
// Define change stream
const changeStream = collection.watch(pipeline);
// start listen to changes
changeStream.on("change", function(event) {
console.log(JSON.stringify(event));
});
});
{
"_id":{
"_data":"825C5D51F70000000129295A1004E83608EE8F1B4FBABDCEE73D5BF31FC946645F696400645C5D51F73ACA83479B48DE6E0004"},
"operationType":"insert",
"clusterTime":"6655565945622233089",
"fullDocument":{
"_id":"5c5d51f73aca83479b48de6e",
"ticker":"AAPL",
"Price":300
},
"ns":{"db":"mydb","coll":"Stocks"},
"documentKey":{"_id":"5c5d51f73aca83479b48de6e"}
}
*/

2 changes: 1 addition & 1 deletion backend/services/passport_ex/package.json
Expand Up @@ -9,7 +9,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"axios": "^0.16.1",
"axios": "^0.18.1",
"dotenv": "^6.0.0",
"express": "^4.15.2",
"express-session": "^1.15.2",
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 5fda3b5

Please sign in to comment.