How do you use require() within a map function? - javascript

Looking at the docs for CouchDB 1.6.1 here, there is mention that you can use the JS require(path) function. How do you do this? The documentation says path is "A CommonJS module path started from design document root".
My design doc is called _design/data. I have uploaded an attachment to this design doc called test.js, which can be accessed at /_design/data/test.js, and contains the following code:
exports.stuff = function() {
this.getMsg = (function() {
return 'hi';
})()
}
But the following code in my map function:
function(doc) {
try {
var x = require('test.js');
} catch (e) {
emit ('error', e)
}
}
results in this error:
["error", "invalid_require_path", "Object has no property \"test.js\". {\"views\":{\"lib\":null},\"_module_cache\":{}}"]
It looks like require is looking for the path as an object in the docparam... but I don't understand why if it is.
Looking at this link, describing this feature in an older version of CouchDB, it says you can:
However, in the upcoming CouchDB 1.1.x views will be able to require modules provided they exist below the 'views' property (eg, 'views/lib/module')
And gives the following code example:
{
"_id": "_design/example",
"lib": {
// modules here would not be accessible from view functions
},
"views": {
"lib" {
// this module is accessible from view functions
"module": "exports.test = 'asdf';"
},
"commonjs": {
"map": function (doc) {
var val = require('views/lib/module').test;
emit(doc._id, val);
}
}
}
}
But this did not work for me on CouchDB 1.6.1. I get the error:
{message: "mod.current is null", fileName: "/usr/share/couchdb/server/main.js", lineNumber: 1137, stack: "([object Array],[object Object])#/usr/share/couchdb/server/main.js:1137\n([object Array],[object Object])#/usr/share/couchdb/server/main.js:1143\n([object Array],[object Object],[object Object])#/usr/share/couchdb/server/main.js:1143\n(\"views/lib/module\")#/usr/share/couchdb/server/main.js:1173\n([object Object])#undefined:3\n([object Object])#/usr/share/couchdb/server/main.js:1394\n()#/usr/share/couchdb/server/main.js:1562\n#/usr/share/couchdb/server/main.js:1573\n"

In your question you didn't provide the function as a string. It's not too easy to spot, but you must stringify functions before storing them in CouchDB (manually or by using .toString()). Caolan has that error in the post that you linked.

Using this example:
15 views: {
16 lib: {
17 foo: "exports.bar = 42;"
18 },
19 test: {
20 map: "function(doc) { emit(doc._id, require('views/lib/foo').bar); }"
21 }
22 }
Found in older CouchDB docs here: https://wiki.apache.org/couchdb/CommonJS_Modules
I got an example working. Not sure what the difference was really... I was running 'temp' views instead of saving but I don't know why that would have effected the require statement

Related

Can't createChatThread() with Preview 4 azure-sdk-for-js

The example code snippet # https://github.com/Azure/azure-sdk-for-js/tree/%40azure/communication-identity_1.0.0-beta.4/sdk/communication/communication-chat does NOT compile.
import { ChatClient, ChatThreadClient } from '#azure/communication-chat';
import { AzureCommunicationTokenCredential } from '#azure/communication-common';
let createChatThreadRequest =
{
topic: 'Preparation for London conference',
participants:
[
{
user: { communicationUserId: '<USER_ID_FOR_JACK>' },
displayName: 'Jack'
},
{
user: { communicationUserId: '<USER_ID_FOR_GEETA>' },
displayName: 'Geeta'
}
]
};
let createChatThreadResponse = await chatClient.createChatThread(createChatThreadRequest);
let threadId = createChatThreadResponse.chatThread.id;
my package.json:
"#azure/communication-identity": "1.0.0-beta.4",
"#azure/communication-calling": "1.0.0-beta.6",
"#azure/communication-chat": "1.0.0-beta.4",
"#azure/communication-common": "1.0.0-beta.5",
"#azure/communication-signaling": "1.0.0-beta.2",
Latest attempt:
createChatThreadRequest:
{
"topic": "Ghost Frog",
"participants": [
{
"user": {
"communicationUserId": "ey...Ug"
},
"displayName": "frog"
}
]
}
POST error 400
https://########.communication.azure.com/chat/threads?api-version=2020-11-01-preview3
RestError: {"error":{"code":"BadRequest","message":"One or more validation errors occurred.","details":[{"message":"The value provided for Id is invalid.","target":"Participants[0].Id"}]}}
The error message is looking for a property named 'Id'. The spec does NOT require an Id. Arg.
sorry you are running into issues and thank you for reaching out!
Someone on our team has tested out your code snippet and SDK versions and it compiled. Can you specify the error codes you are seeing? It will help us understand the issue better. Thanks!
given you are using version 1.0.0-beta.4 I can verify the code snippet you have is correct.
In the latest release of the JS SDK 1.0.0-beta.5 the user property was in fact renamed to id, however previous versions should still work as expected.
Can you verify if the latest version works for you? The error you are seeing can also occur if an invalid communicationUserId is provided.
Given your current version and code, if the issue is persisting we would like to investigate.
We try to keep these docs up to date during public preview but if you run into issues please let us know:
https://github.com/Azure/azure-sdk-for-js/tree/master/sdk/communication/communication-chat
https://learn.microsoft.com/en-us/azure/communication-services/quickstarts/chat/get-started?pivots=programming-language-javascript

JS Object strange behaviour when trying access Loopback related model query

I am working with the Loopback Framework, doing a web project.
But I think that the question that I am exposing here has less to do with this, but with general Javascript / Node.JS knowledge.
At one part of the code, I am doing:
roleMapping.find({
where: {
principalType: 'USER',
principalId: context.principals[0].id
},
include: 'role'
}, function(err, roles){
console.log(roles[0]);
for (var i in roles)
{
if (roles[i].role.name === 'teamLeader' &&
roles[i].groupId === context.modelId)
{
cb(null,true);
}else {
cb(null,false);
}
}
});
Ok with this, but it fails when trying to compare roles[i].role.name.
So, I went logging what the roles[i] object contained.
{ groupId: 1,
id: 3,
principalType: 'USER',
principalId: 1,
roleId: 2,
role:
{ id: 2,
name: 'teamLeader',
description: 'The leader(s) of a team',
created: null,
modified: null } }
Ok, nothing wrong, but it still fails, so I tried to print just the role property. And to my surprise:
{ [Function]
update: [Function],
destroy: [Function],
create: [Function],
build: [Function],
_targetClass: 'Role' }
So, the role property seems to be some sort of function? But how it was been correctly printed before?
Eventually, lost in my frustration I tried var role = JSON.parse(JSON.stringify(roles[i]));
And then I could access every property of the object normally, but this is not clean nor normal.
This blew my mind for the first time in years of JS programming (sort of amateurish though), and I would be pleased if someone could clarify this to me. Thanks
EDIT: It seems that it is specific to this Framework, so I'm changing title to help community.
I just found issue 1425 which links to the following docs:
With Node.js API, you need to call toJSON() to convert the returned model instance with related items into a plain JSON object
Please note the relation properties […] points to a JavaScript function for the relation method.
So it seems you have to use
for (var i=0; i<roles.length; i++) {
var x = roles[i].toJSON();
cb(null, x.role.name === 'teamLeader'
&& x.groupId === context.modelId);
}

Why is log4js creating an empty file but never putting messages into it?

log4js creates an empty file. I've looked at the answers to the (many) other times this happens to people on SO, but none seem relevant to me. Here is my code:
// Configure logging.
require('log4js').configure('log4js.json');
var logger = require('log4js').getLogger();
logger.info('Starting Engine');
And my log4js.json file is pretty standard:
{
"appenders": [
{
"type": "file",
"filename": "main.log",
"maxLogSize": 20480,
"backups": 3,
"category": "relative-logger"
}
]
}
Is there any actual documentation for this project? It feels like its a poor cousin to the real log4j, and they are just freeloading off log4j's good reputation.
Edit:
Here is an almost word for word copy of an example which (surprise surprise) doesn't work:
var log4js = require('log4js');
log4js.configure({
appenders: [
{ type: 'console' },
{ type: 'file', filename: "test.log", category: 'my_project' }
]
});
var logger = log4js.getLogger('my_project');
//logger.setLevel('DEBUG');
logger.log('Why does node.js not have any decent logging frameworks??');
It returns the following:
return this.level <= otherLevel.level;
^
TypeError: Cannot read property 'level' of undefined
at Level.isLessThanOrEqualTo (xxxx\node_modules\log4js\lib\levels.js:41:34)
at Logger.isLevelEnabled (xxxx\node_modules\log4js\lib\logger.js:63:21)
at Logger.log (xxxx\node_modules\log4js\lib\logger.js:56:12)
it appears you are using log4js incorrectly. there is no function called log in object logger. Use any of the following:
logger.trace('Entering cheese testing');
logger.debug('Got cheese.');
logger.info('Cheese is Gouda.');
logger.warn('Cheese is quite smelly.');
logger.error('Cheese %s is too ripe!', "gouda");
logger.fatal('Cheese was breeding ground for listeria.');
So. the problem (and im still not sure why) is that this:
require('log4js').configure('log4js.json');
var logger = require('log4js').getLogger();
Needs to be written thus:
var log4js = require('log4js');
log4js.configure('log4js.json');
var logger = log4js.getLogger();
Being clever and doing a require() twice on log4js seems to cause chaos.

knockout.js ReferenceError - Unable to parse bindings $data is not defined

I am writing Jasmine test that is using mocked database response from WebSQL database. In following code segment I am getting an error.
function createCalculatedField(calculatedValue, objectContext) {
var computedObservable = ko.computed({
read: function () {
return ko.unwrap(ko.bindingProvider.instance.parseBindingsString("text: " + calculatedValue, objectContext).text);
},
write: function (value) {
computedObservable.notifySubscribers(value);
},
owner: objectContext
});
error message I am getting is following:
ReferenceError: Unable to parse bindings. Bindings value: text: ko.unwrap(PagingStartIndex) + $context().length Message: $data is not defined
I have printed out function inputs, and reproduced the error into Chrome console in screenshot below.
upon inspection of knockout-3.0.0.custom.min.js parseBindingsString method on which it fails.
function (b,c,d,e){try{var f=this.bindingCache,h=b+(e&&e.valueAccessors||""),g;if(!(g=f[h])){var n,k="with($context){with($data||{}){return{"+a.expressionRewriting.preProcessBindings(b,e)+"}}}";n=new Function("$context","$element",k);g=f[h]=n}return g(c,d)}catch(p){throw p.message="Unable to parse bindings.\nBindings value: "+
b+"\nMessage: "+p.message,p;}}
I can see that $data is internal knockout.js parameter. This same code works just fine in production environment, so I am assuming I am not setting something somewhere, could you point me in direction on how to debug this issue, cause I am totally out of ideas at this point.
Internally, Knockout uses the following dynamic function to evaluate your expression
function($context, $element) {
with($context) {
with($data||{}) {
return {text: ko.unwrap(PagingStartIndex) + $context().length};
}
}
}
If you look at the object that is normally passed into the parseBindingsString by knockout it looks like...
{
$data: {...},
$index: ko.observable(),
$parent: {...},
$parentContext: ko.bindingContext,
$parents: [...],
$root: {...}
}
This object graph is normally created by invoking new ko.bindingContext(...) or, if you are within a custom binding, bindingContext.createChildContext(...)
Looking at your screenshot it looks like objectContext is an observableArray containing 2 elements and I'm also assuming you manually created the objectContext instance in your jasmine tests.
Therefore the object you are passing into the parseBindingString ( which comes into the dynamic function as $context ) does not have a $data field, that is the reason the exception is thrown.
The should have the object graph similar to the normal bindingContext object where the value of $data is your model
i.e.
{
$data: ko.observableArray: ( [
{
Fields:{...},
Insert: false,
SetFields:[]
}, {
Fields:{},
Insert: false,
SetFields: []
}] ),
$index: ko.observable(),
...
}
However, you will still get an error message in this instance as PagingStartIndex is missing from $data object, the same as if you got a mismatch between your binding expression and the model in your production system.

Passing bootstrapped variables and JSON to require.js

What is the best practice for passing bootstrapped variables within the rendered page (i.e. JSON data or config variables) to require.js so they can be checked for an used by dependancies?
It looks like this could be done by checking the window object (i.e. window.bootstrapped_models but that does not seem very optimal.
app.html - example data within the HTML document
<script>
var config = {
"isAdmin": true,
"userId": 1
};
var bootstrapped_models = {
"groups": [
{
"id": 1,
"name": "Foo"
},
{
"id": 2,
"name": "Bar"
}
]
}
</script>
app.js - example app using require()
require(['jquery', 'GroupCollection'], function($, GroupCollection) {
// extend default config
if (config) {
$.extend(defaults, config);
}
// use bootstrapped JSON here
var collection = new GroupCollection;
if (bootstrapped_models.groups.length > 0) {
collection.add(bootstrapped_models.groups);
}
});
The answer from #timDunham was helpful, but it felt a little overly complicated to me. Playing around with require.js and Lithium (PHP MVC) I came up with the following. It's simple and has worked in each instance I've run into.
<script type="text/javascript">
define('bootstrapData', function () {
return <?php echo json_encode($bootstrapData) ?>;
});
</script>
Which is then available by doing the following:
define(['bootstrapData'], function(bootstrapData) {
console.log(bootstrapData); // Will output your bootstrapped object
});
Obviously the way I'm bringing the data in is language specific, but the rest should be useful regardless of your situation.
Not sure if my method is best practice but I do something a lot like what you are doing except instead of butting the bootstrapped models on the global object, I create a define for it in my HTML page:
<script type="text/javascript">
define("bootstrappedModelJson", function() {
return #Html.Action("Controller", "RenderModel");
});
require({
baseUrl: //etc.
}, ["app"],
function(){
});
</script>
then I have a js file called current.model that can be required by other modules and looks like this:
define(
[
'require',
'model'
],
function (require, Model)
{
var json= require("bootstrappedModelJson");
return new Model(json);
});
You can solve problems with optimize/build by disabling the bootstrapData in your build.js
Like this:
paths: {
bootstrapData: "empty:",

Categories

Resources