Normaly I'm using ES6 syntax to import things from another file:
target.js
import { articles } from '/imports/fixtures.js'
console.log(articles.main)
fixtures.js
export const
articles = {
main: { _id: '1234', title: 'anything' }
}
Now I need to use the fixtures.js file in some testing modules, which needs the require syntax.
But this would not work:
var { articles } = require('/imports/fixtures.js')
What is the correct syntax for this?
Destructuring assignement is a recent feature, if your version of javascript (I guess of nodejs) is prior to ES2015, you could use:
var articles = require('/imports/fixtures.js').articles
N.B: NodeJS supports of desctructuring assignment start with v6.
if you are exporting articles as a single object, you need to receive as a single object.
For This
export const
articles = {
main: { _id: '1234', title: 'anything' }
}
Use This
var articles = require('/imports/fixtures.js');
For main
This will open the articles object and take out main and store it in a variable main in target.js.
var {main} = require('/imports/fixtures.js');
Related
What is the following statement doing, and why use const vs var?
const { SearchIcon } = myApp.icons;
For context, I am learning Vue and new to Javascript. I saw this in an example. The SearchIcon is an icon that is being imported from heroicons, MyApp.icons is being defined in a different script file like this:
window.MyApp = {
app: null,
icons: {},
...
Looks like your issue is that you're storing MyApp under window, but then trying to access it directly. You've also got a capital M in the definition, and a lowercase when your accessing it.
Here's a working example:
window.MyApp = {
app: null,
icons: {
SearchIcon : 'Hello!'
},
};
const { SearchIcon } = window.MyApp.icons;
console.log(SearchIcon);
For more info, see the docs on object destructuring.
Hope that helps :)
I have a basic database that essentially stores an array of product id's underneath a user. The user can select products to add to the array so it makes sense to use 'arrayUnion' so I avoid reading and re-writing the array constantly, however, I keep getting the error *"Property 'firestore' does not exist on type 'FirebaseNamespace'."
I've followed the documentation found at: https://firebase.google.com/docs/firestore/manage-data/add-data#update_elements_in_an_array but I fear I'm still using it incorrectly.
My code for updating the array is:
addToPad(notepadName: string){
const updateRef = this.db.collection('users').doc(this.activeUserID).collection('notepads').doc(notepadName);
updateRef.update({
products: firebase.firestore.FieldValue.arrayUnion(this.productId)
});
}
First you need to import firestore:
import { firestore } from 'firebase/app';
Then you will be able to use arrayUnion:
addToPad(notepadName: string){
const updateRef = this.db.collection('users').doc(this.activeUserID).collection('notepads').doc(notepadName);
updateRef.update({
products: firestore.FieldValue.arrayUnion(this.productId)
});
}
import { arrayUnion } from '#angular/fire/firestore'
const path = `ai/${videoId}/panel-operation/${id}`
const myDoc: AngularFirestoreDocument<any> = this.afs.doc<any>(path)
const promise: Promise<void> = myDoc.update({ auxPanelSelections: arrayUnion({auxPanel: 'clip', operation: 'replace'}) }).catch((err: any) => {
console.error(`oopsie - ${err.message}`)
return null
})
auxPanelSelections is an array within the myDoc document
Note that the above code also works perfectly fine with arrayRemove
I cannot find the #angular/fire docs for arrayUnion but the generic docs are here
I'm trying to write a Vue plugin that's a simple abstraction to manage auth state across my app. This will need to access other Vue plugins, namely vuex, vue-router and vue-apollo (at the moment).
I tried extending Vue.prototype but when I try to access the plugin's properties how I would normally - eg. this.$apollo - I get the scope of the object, and therefore an undefined error. I also tried adding vm = this and using vm.$apollo, but this only moves the scope out further, but not to the Vue object - I guess this is because there is no instance of the Vue object yet?
export const VueAuth = {
install (Vue, _opts) {
Vue.prototype.$auth = {
test () {
console.log(this.$apollo)
}
}
}
}
(The other plugins are imported and added via. Vue.use() in the main app.js)
Alternatively, I tried...
// ...
install (Vue, { router, store, apollo })
// ...
but as a novice with js, I'm not sure how this works in terms of passing a copy of the passed objects, or if it will mutate the originals/pass by ref. And it's also very explicit and means more overhead if my plugin is to reach out to more plugins further down the line.
Can anyone advise on a clean, manageable way to do this? Do I have to instead alter an instance of Vue instead of the prototype?
In the plugin install function, you do not have access to the Vue instance (this), but you can access other plugins via the prototype. For example:
main.js:
Vue.use(Apollo)
Vue.use(VueAuth) // must be installed after vue-apollo
plugin.js:
export const VueAuth = {
install (Vue) {
Vue.prototype.$auth = {
test () {
console.log(Vue.prototype.$apollo)
}
}
}
}
I found a simple solution for this issue:
In plugin installer you need to add value to not just prototype, but Vue itself to be able to use it globally.
There is a code example:
Installer:
import apiService from "../services/ApiService";
// Service contains 'post' method
export default {
install(Vue) {
Vue.prototype.$api = apiService;
Vue.api = apiService;
}
};
Usage in other plugin:
import Vue from "vue";
...
const response = await Vue.api.post({
url: "/login",
payload: { email, password }
});
Usage in component:
const response = await this.$api.post({
url: "/login",
payload: { email, password }
});
I'm not sure if that's a good solution, but that made my scenario work perfectly.
So, I got around this by converting my property from a plain ol' object into a closure that returns an object, and this seems to have resolved my this scoping issue.
Honestly, I've jumped into Vue with minimal JS-specific knowledge and I don't fully understand how functions and the likes are scoped (and I'm not sure I want to look under that rock just yet......).
export const VueAuth = {
install (Vue, opts) {
Vue.prototype.$auth = function () {
let apollo = this.$apolloProvider.defaultClient
let router = this.$router
return {
logIn: function (email, password) {
apollo.mutate({
mutation: LOGIN_MUTATION,
variables: {
username: email,
password: password,
},
}).then((result) => {
// Result
console.log(result)
localStorage.setItem('token', result.data.login.access_token)
router.go(router.currentRoute.path)
}).catch((error) => {
// Error
console.error('Error!')
console.error(error)
})
},
logOut: function () {
localStorage.removeItem('token')
localStorage.removeItem('refresh-token')
router.go()
console.log('Logged out')
},
}
}
It's a rudimental implementation at the moment, but it'll do for testing.
How to make following use case with Flow and nodejs?
Requirements:
have Type definitions in a separate file(s), for now lets say all in Types.js
to use it inside another file/module:
const MyRequiredType = require('Types').MyRequiredType;
const methodWithInputTypeCheck = function(request: MyRequiredType){ }
Tried to use flow-aliases, but this seems to work only when have the declaration in the same file.
Thanks.
Oh, it seems that at the end it is far more simpler.
Looks like we can use std. classes:
1./ Types.js
// #flow
const Types =
{
SomethingWithUserRequest: class MyClass {
userId: string; //thanks to Babel
userNick: string;
}
};
module.exports = Types;
2./ SomeModule.js:
const SomethingWithUserRequest = require('../service/Dto/Types').SomethingWithUserRequest;
const TestFacade =
{
testFlow: function(
request: SomethingWithUserRequest
) {
console.log('userId', request.userId);
}
};
module.exports = TestFacade;
Only the IDE is still confused and does not hint in this way.
I'm very, very new to the whole NodeJS stack, and I'm trying to rough up a simple login system for practice.
Jumping to my question,
app.js
...
var mongoose = require( 'mongoose' );
var templates = require( './data/inc.js' ); // includes schema structures
...
user.js - included in inc.js
...
module.exports =
{
"Schema" : new exports.mongoose.Schema({
"uid": mongoose.Schema.Types.ObjectId,
"username": { type:String, unique:true },
"alias": String,
"credentials":
{
"salt": String,
"password": String,
"key": String
},
"profile":
{
"age": { type: Number, min: 18 }
},
"last_login": Date,
"updated": { type: Date, default: Date.now }
})
}
...
The 'user.js' script above will not work because it doesn't have access to the mongoose object variable instantiated in the 'app.js' script. In PHP any included/required scripts would be able to access variables from the parent script, but in NodeJS as I know it for example I have to re-require/state the mongoose variable in order to create my schema tree.
user.js
...
* var mongoose = require( 'mongoose' ); // must include in script to use mongoose object
module.exports
{
...
}
...
Is there any work-around that will allow me the same scope access as PHP?
The answer is that there are workarounds, but you really don't want to use them, ever, ever, except for things which you want to hack into the global scope of all running modules in your application up to and including all dependencies (mongoose) and all of ITS dependencies.
override.js
global.thisIsNowAvailable = true;
flaky-file.js
if (thisIsNowAvailable) { /* ... */ }
index.js
require("./override");
require("./flaky-file");
The same will work for overriding methods on global prototypes, et cetera.
Unless your library is super-awesome and is intended to intercept, parse and interpret code at require-time
require("babel/register"); // all loaded modules can now be written in ES6
doing this for other reasons leads to horrible code-bases...
broken-index.js
require("flaky-file");
require("override");
// you might have just attempted to reference a variable that doesn't exist,
// thrown an error and crashed your entire server
// (not just a single connection, like PHP... ...the entire server went down,
// for everyone, and it has to be restarted).
Think of modules as separate function scopes.
It's really simple to do something like:
needs-mongoose.js
function doSomeInitWithMongoose (db) { /* ... */ }
function doSomeRuntimeWithMongoose (db, params) { /* ... */ }
module.exports = mongoose => {
doSomeInitWithMongoose(mongoose);
return {
run: params => {
/* ... app is run here ... */
doSomeRuntimeWithMongoose(mongoose, params);
}
};
};
configures-mongoose.js
var mongoose = require("mongoose");
function configure (db, cfg) { /* ... */ return db; }
module.exports = config => {
var configuredDB = configure(mongoose, config);
return configuredDB;
};
main.js
// to support arrow functions and other awesome ES6, including ES6 modules
require("babel/register");
var config = require("./mongoose-config");
var db = require("./configures-mongoose")(config);
var app = require("./needs-mongoose")(db);
app.run({ /* ... */ });
EDIT
Updated the last few files to be a structurally-correct pseudo-program (which does absolutely nothing, of course);
Of course, if index.js or server.js were to require("babel/register"); and then load main.js (without the Babel include in it), all of the require statements south of Babel could be written as ES6 modules, without issue.
server.js
require("babel/register");
require("./es6-main");
es6-main.js
import config from "./mongoose-config";
import configureDB from "./configures-mongoose";
import loadApp from "./needs-mongoose";
const db = configureDB(config);
const app = loadApp(db);
app.run({ /* ... */ });
Note that now I'm naming the functions I was originally returning, because in JS when you return a function, you can immediately call it...
getFunc( config )( data );
...but you can't act immediately on import statements.
Rule of thumb is that if you're going to export an object to the outside world, it should have 0 external dependencies, or all external dependencies will be set up later, by setters of some kind:
var utils = require("./utils"); // doesn't need any information
utils.helperFunc(data);
or
var catsAndPorn = true;
var internets = [];
var SeriesOfTubes = require("series-of-tubes");
var internet = new SeriesOfTubes( catsAndPorn );
internets.push( internet );
or
var bigOlFramework = require("big-ol-framework");
bigOlFramework.setDBPool( myDBCluster );
http.createServer( bigOlFramework.connectionHandler ).listen( 8080 );
None require outside information for their actual init (though may require their own internal dependencies).
If you want to return something which does rely on external init, either export a factory/constructor, or export a function, which accepts your config/data, and then returns what you want, after an init sequence.
EDIT 2
The last piece of advice here is that as far as mongoose usage goes, or Gulp, to a similar extent, or several routers...
...when you want to have a single file which registers its contents to a registry, or requires a core-component, to be able to return something, the pattern in Node which makes the most sense is to return a function which then does the init
var Router = require("router");
var router = new Router( );
require("./routes/login")(router);
require("./routes/usesrs")(router);
require("./routes/articles")(router);
Where "./routes/articles.js" might look like
import ArticlesController from "./../controller/articles"; // or wherever
var articles = new ArticlesController();
module.exports = router => {
router.get("/articles", ( ) => articles.getAll( ));
router.post("/articles", ( ) => articles.create( ));
};
So if you were looking to structure ORM based on schema, you might do similar:
var mongoose = require("mongoose");
var Users = require("./schema/users")(mongoose);
where "./schema/users" looks like:
module.exports = mongoose => {
return new mongoose.Schema({ /* ... */ });
};
Hope that helps.
Why don't you just do this?
var mongoose = require( 'mongoose' );
...
"Schema" : new mongoose.Schema({
Instead of:
exports.mongoose.Schema // I'm not sure where you got `exports.mongoose` from.
Also you don't have to use the .js when requiring like:
var templates = require( './data/inc' );
Edit
I believe you can't do it like PHP. Also the requires are cached so no need to worry about re requiring.