mean.js uses require without var - express

Have a question with regards to the default meanjs app from yeoman.
Inside the express.js file it has a statement like so:
// Globbing model files
config.getGlobbedFiles('./app/models/**/*.js').forEach(function(modelPath) {
require(path.resolve(modelPath));
});
Now I understand that it gets all the .js files inside the path "./app/models/", but what I am trying to understand is the alone standing
require(path.resolve(modelPath));
How is the require function being used without it being set to a "var"?
An example of one of these included files is like this:
'use strict';
/**
* Module dependencies.
*/
var mongoose = require('mongoose'),
Schema = mongoose.Schema;
/**
* Article Schema
*/
var ArticleSchema = new Schema({
created: {
type: Date,
default: Date.now
},
title: {
type: String,
default: '',
trim: true,
required: 'Title cannot be blank'
},
content: {
type: String,
default: '',
trim: true
},
user: {
type: Schema.ObjectId,
ref: 'User'
}
});
mongoose.model('Article', ArticleSchema);
This file doesn't expose anything.
So why is the require being called with a "var" and without the contents exposing a function?
How will this allow for the contents to be used later?

The code in the express.js file executes the contents of your model files. The anatomy of a MEAN.js model file is the following;
Load the mongoose and schema packages, along with all your included
models (if any).
Declare the schema for the given model
Register the given schema under the model name (Article for the given example).
There is nothing to return, hence the lack of any variable assignment in the express.js file. From now on you can call models by the label you assigned in the third part. Therefore, in your controller, you would write something like;
var articles = Article.query();
This line of code would load up the Article schema and run the provided query() method in your back-end (which by default returns all the instances in the database under that model).
In general, remember; not all functions return something.

Related

NestJS serialization from snake_case to camelCase

I want to achieve automatic serialization/deserialization of JSON request/response body for NestJS controllers, to be precise, automatically convert snake_case request body JSON keys to camelCase received at my controller handler and vice versa.
What I found is to use class-transformer's #Expose({ name: 'selling_price' }), as on the example below (I'm using MikroORM):
// recipe.entity.ts
#Entity()
export class Recipe extends BaseEntity {
#Property()
name: string;
#Expose({ name: 'selling_price' })
#Property()
sellingPrice: number;
}
// recipe.controller.ts
#Controller('recipes')
export class RecipeController {
constructor(private readonly service: RecipeService) {}
#Post()
async createOne(#Body() data: Recipe): Promise<Recipe> {
console.log(data);
return this.service.createOne(data);
}
}
// example request body
{
"name": "Recipe 1",
"selling_price": 50000
}
// log on the RecipeController.createOne handler method
{ name: 'Recipe 1',
selling_price: 50000 }
// what I wanted on the log
{ name: 'Recipe 1',
sellingPrice: 50000 }
There can be seen that the #Expose annotation works perfectly, but going further I want to be able to convert it as the attribute's name on the entity: sellingPrice, so I can directly pass the parsed request body to my service and to my repository method this.recipeRepository.create(data). Current condition is the sellingPrice field would be null because there exists the selling_price field instead. If I don't use #Expose, the request JSON would need to be written on camelCase and that's not what I prefer.
I can do DTOs and constructors and assigning fields, but I think that's rather repetitive and I'll have a lot of fields to convert due to my naming preference: snake_case on JSON and database columns and camelCase on all of the JS/TS parts.
Is there a way I can do the trick cleanly? Maybe there's a solution already. Perhaps a global interceptor to convert all snake_case to camel_case but I'm not really sure how to implement one either.
Thanks!
You could use mapResult() method from the ORM, that is responsible for mapping raw db results (so snake_case for you) to entity property names (so camelCase for you):
const meta = em.getMetadata().get('Recipe');
const data = {
name: 'Recipe 1',
selling_price: 50000,
};
const res = em.getDriver().mapResult(data, meta);
console.log(res); // dumps `{ name: 'Recipe 1', sellingPrice: 50000 }`
This method operates based on the entity metadata, changing keys from fieldName (which defaults to the value based on selected naming strategy).

Dexie.js table.name isn't working even though the table is under the tables property

I'm wanting to fetch all items from a table into a collection but am getting an error that the table name is undefined. Here is my store:
db.version(1).stores({
users: '++id,',
orgs: '++id,',
applications: '++id'
})
Then later here is my call:
db.orgs.toCollection().count(function (count) {
console.log(count)
})
It gives the following error:
TypeError: Cannot read property 'toCollection' of undefined
But when I stop the debugger at the call and type in db.tables sure enough:
1:Table {name: "orgs", schema: TableSchema, _tx: undefined, …}
_tx:undefined
hook:function rv(eventName, subscriber) { … }
name:"orgs"
Any help is appreciated - thanks.
UPDATE
I noticed that when I seeded the database on initial creation I could fetch the data out. So I copied in that code into my template. It still fails however, so there must be something simple I'm missing, here is that code:
import Dexie from '#/dexie.es.js'
export default {
name: 'ListOrgs',
data: () => {
return {
orgs: []
}
},
methods: {
populateOrgs: async function () {
let db = await new Dexie('myDatabase').open()
db.orgs.toCollection().count(function (count) {
console.log(count)
})
}
},
mounted () {
this.populateOrgs()
}
}
Dexie has two modes
Static - the most common one used in most samples.
Dynamic - Schema is not specified in code.
Static Mode
//
// Static Mode
//
const db = new Dexie('myDatabase');
db.version(1).stores({myTable1: '++'});
db.version(2).stores({myTable1: '++, foo'});
db.myTable1.add({foo: 'bar'}); // OK - dexie knows about myTable1!
Dynamic Mode
//
// Dynamic Mode
//
const db = new Dexie('myDatabase');
// FAIL: db.myTable1.add({foo: 'bar'}); // myTable1 is unknown to the API.
// Here, you must wait for db to open, and then access tables using db.table() method:
db.open().then(db => {
const myTable = db.table('myTable');
if (myTable) {
myTable.add({foo: 'bar'});
}
}).catch(error => {
console.error(error);
});
If omitting any version() specification, Dexie will just try to open any existing database with the same name, no matter version or schema. But it won't create the implicit table properties onto the db instance.
When Dynamic Mode is Useful
Dynamic mode can be useful when building an arbritary database utility that should adapt to any indexedDB database - such as a DB explorer. Dynamic mode can also be useful when the javascript code is by design not aware of the schema (what tables are expected to be queried and what indexes there are).
Benefits with Static Mode
No need to wait for db.open() to complete.
Automatic DB creation when neeeded. No complex app code to deal with database versioning.
Automatic DB population when needed.
Design Patterns in Static Mode
db.js
import Dexie from 'dexie';
//
// Let this module do several things:
//
// * Create the singleton Dexie instance for your application.
// * Declare it's schema (and version history / migrations)
// * (Populate default data http://dexie.org/docs/Dexie/Dexie.on.populate)
//
export const db = new Dexie('myDatabase');
db.version(1).stores({
users: '++id,',
orgs: '++id,',
applications: '++id'
});
db.on('populate', () => {
return db.orgs.bulkAdd([
{'foo': 'bar'},
]);
});
app.js
import {db} from './db';
// Wherever you use the database, include your own db module
// instead of creating a new Dexie(). This way your code will
// always make sure to create or upgrade your database whichever
// of your modules that comes first in accessing the database.
//
// You will not have to take care of creation or upgrading scenarios.
//
// Let Dexie do that for you instead.
//
async function countOrgs() {
return await db.orgs.count();
}

Conditional sails model schemas

I'm trying write a conditional model schema based if exists other models.
For example, if exist model 'Message' then add a inbox/outbox:
var userSchema = {
attributes: {
...
}
}
var messageSchema = {
attributes: {
inbox: {
collection: 'Message'
},
outbox: {
collection: 'Message'
}
}
};
if (<function to check that Message Model is available)
_.merge userSchema, messageSchema
Is it possible do something like this?
I think we need one "pre model load" fase on plugins and one hook to alow others modules do alter it structure like drupal 7 scheme.
You cold exports one function to plug this "fase feature" in plugin npm loader like i did with default configs: https://github.com/wejs/we-plugin/blob/master/lib/index.js#L18 and set in https://github.com/wejs/we-example/blob/master/app.js#L63

How to retrieve stores based on the store id

I am creating a Memory store as
var someData = [
{id:1, name:"One"},
{id:2, name:"Two"}
];
store = new Memory({
data: someData,
id:”userStore”
});
I was wondering if there is a way to query the Memory store to return the store instance by id. Like
var storePresent = Memory.getById(“userStore”)
something similar to
dijit.registry.byId();
that returns the instance of dijit specified by id
To my knowledge, there is not a store registry as you describe. You will need to code this yourself in your application's controller code.
A store is a simple Object.
You could:
Pass the store manually around your code.
Code a registry AMD module (caution, here be dragons).
The only exception to this rule is if you're already using dojox/app as your controller layer. That has some named store abilities. If not, I would not recommend refactoring to use it.
There's no build-in static repository of memory stores in module dojo/store/Memory. If you need something like that, the easiest way is to write custom factory of memory stores that will hold the static references to all stores that are created:
define(["dojo/store/Memory"], function(Memory){
var repository = {}
return {
getStore: function(id) {
return repository[id]
},
createStore: function(id, params) {
var memory = new Memory(params)
repository[id] = memory
return memory
}
}
});
The usage:
require(["modules/MemoryRepository"], function(MemoryRepository) {
MemoryRepository.createStore("userStore", {data: someData})
...
var userStore = MemoryRepository.getStore("userStore")
})
If you are to create a lot of stores on demand, you should think of deregistering them (removing the references from the factory) as well. Memory issues are probably the reason something like that is not provided out-of-the-box.
Like the other answerers already said, there's no specific repository or registry for stores. However, the dijit/registry can be used to store the reference as well by using the dijit/registry::add() function, for example:
// Add to registry
registry.add(new Memory({
id: "userStore",
data: [{
name: "Smith",
firstname: "John"
}, {
name: "Doe",
firstname: "John"
}]
}));
Then you can retrieve it by using the dijit/registry::byId() function, for example:
// Query the store by using the registry
var person = registry.byId("userStore").query({
firstname: "John"
}).forEach(function(person) {
console.log(person.firstname + " " + person.name);
});
A full example can be found on JSFiddle: http://jsfiddle.net/mn94f/

Sproutcore datasources and model relationships

I currently have a Sproutcore app setup with the following relationships on my models:
App.Client = SC.Record.extend({
name: SC.Record.attr(String),
brands: SC.Record.toMany('App.Brand', {isMaster: YES, inverse: 'client'})
});
App.Brand = SC.Record.extend({
name: SC.Record.attr(String),
client: SC.Record.toOne('App.Client, {isMaster: NO, inverse: 'brands'})
});
When I was working with fixtures my fixture for a client looked like this:
{
guid: 1,
name: 'My client',
brands: [1, 2]
}
And my fixture for a brand looked like this:
{
guid: 1,
name: 'My brand',
client: 1
}
Which all worked fine for me getting a clients brands and getting a brands client.
My question is in regards to how Datasources then fit into this and how the server response should be formatted.
Should the data returned from the server mirror exactly the format of the fixtures file? So clients should always contain a brands property containing an array of brand ids? And vice versa.
If I have a source list view which displays Clients with brands below them grouped. How would I go about loading that data for the source view with my datasource? Should I make a call to the server to get all the Clients and then follow that up with a call to fetch all the brands?
Thanks
Mark
The json you return will mostly mirror the fixtures. I recently had pretty much the same question as you, so I built a backend in Grails and a front end in SC, just to explore the store and datasources. My models are:
Scds.Project = SC.Record.extend(
/** #scope Scds.Project.prototype */ {
primaryKey: 'id',
name: SC.Record.attr(String),
tasks: SC.Record.toMany("Scds.Task", {
isMaster: YES,
inverse: 'project'
})
});
Scds.Task = SC.Record.extend(
/** #scope Scds.Task.prototype */ {
name: SC.Record.attr(String),
project: SC.Record.toOne("Scds.Project", {
isMaster: NO
})
});
The json returned for Projects is
[{"id":1,"name":"Project 1","tasks":[1,2,3,4,5]},{"id":2,"name":"Project 2","tasks":[6,7,8]}]
and the json returned for tasks, when I select a Project, is
{"id":1,"name":"task 1"}
obviously, this is the json for 1 task only. If you look in the projects json, you see that i put a "tasks" array with ids in it -- thats how the internals know which tasks to get. so to answer your first question, you dont need the id from child to parent, you need the parent to load with all the children, so the json does not match the fixtures exactly.
Now, it gets a bit tricky. When I load the app, I do a query to get all the Projects. The store calls the fetch method on the datasource. Here is my implementation.
Scds.PROJECTS_QUERY = SC.Query.local(Scds.Project);
var projects = Scds.store.find(Scds.PROJECTS_QUERY);
...
fetch: function(store, query) {
console.log('fetch called');
if (query === Scds.PROJECTS_QUERY) {
console.log('fetch projects');
SC.Request.getUrl('scds/project/list').json().
notify(this, '_projectsLoaded', store, query).
send();
} else if (query === Scds.TASKS_QUERY) {
console.log('tasks query');
}
return YES; // return YES if you handled the query
},
_projectsLoaded: function(response, store, query) {
console.log('projects loaded....');
if (SC.ok(response)) {
var recordType = query.get('recordType'),
records = response.get('body');
store.loadRecords(recordType, records);
store.dataSourceDidFetchQuery(query);
Scds.Statechart.sendEvent('projectsLoaded')
} else {
console.log('oops...error loading projects');
// Tell the store that your server returned an error
store.dataSourceDidErrorQuery(query, response);
}
}
This will get the Projects, but not the tasks. Sproutcore knows that as soon as I access the tasks array on a Project, it needs to get them. What it does is call retrieveRecords in the datasource. That method in turn calls retrieveRecord for every id in the tasks array. My retrieveRecord method looks like
retrieveRecord: function(store, storeKey) {
var id = Scds.store.idFor(storeKey);
console.log('retrieveRecord called with [storeKey, id] [%#, %#]'.fmt(storeKey, id));
SC.Request.getUrl('scds/task/get/%#'.fmt(id)).json().
notify(this, "_didRetrieveRecord", store, storeKey).
send();
return YES;
},
_didRetrieveRecord: function(response, store, storeKey) {
if (SC.ok(response)) {
console.log('succesfully loaded task %#'.fmt(response.get('body')));
var dataHash = response.get('body');
store.dataSourceDidComplete(storeKey, dataHash);
} ...
},
Note that you should use sc-gen to generate your datasource, because it provides a fairly well flushed out stub that guides you towards the methods you need to implement. It does not provide a retrieveMethods implementation, but you can provide your own if you don't want to do a single request for each child record you are loading.
Note that you always have options. If I wanted to, I could have created a Tasks query and loaded all the tasks data up front, that way I wouldn't need to go to my server when I clicked a project. So in answer to your second question, it depends. You can either load the brands when you click on the client, or you can load all the data up front, which is probably a good idea if there isn't that much data.