jurisv / nodejs.extdirect Goto Github PK
View Code? Open in Web Editor NEWExt.Direct connector for node.js (npm module)
Ext.Direct connector for node.js (npm module)
In the readme.md, the script link /directapi is inside the x-compile block. Doing so causes a sencha cmd compile error.
Since /directapi appears to be served by the node.js app, It seems like it should be placed outside the x-compile block.
It's very painful to have to copy paste code from a README.md file. What's really needed is a complete working example that is versioned by source file. It's also important that this example code is not part of this repo so it's not included in any package dependency. Just update the README.md to point to this new example repo.
Thanks for extdirect for NodeJS ... really appreciated!
Take in to consideration: #17
Hi i'm sorry for my bad english it's not my natural language.
It could be usefull to have more than one apipath, it would help to get a better general code organization, like that, it lets us to have many apipath
ExtDirectConfig.apiPath("/directapi;/directapi2")
or with array
ExtDirectConfig.apiPath(["/directapi","/directapi2"])
Whenever I try to start the demo-app, I get the following error from node.js
/Library/Server/Node/mysql/direct/.DS_Store:1
(function (exports, require, module, __filename, __dirname) {
SyntaxError: Unexpected token ILLEGAL
When deleting the file .DS_Store in the /direct folder the app starts once but immediately crashes again when trying to execute a function.
If you declare a set of API functions sootstvetsvii with ES6, ie without the keyword FUNCTION, the library fails parsing function arguments.
Error text:
\node_modules\extdirect\lib\api.js:194
var r = argDecl[1].split(FN_ARG_SPLIT);
^
TypeError: Cannot read property '1' of null
at API.__dirname.API.config.reflection (\node_modules\extdirect\lib\api.js:194:28)
at \node_modules\extdirect\lib\api.js:85:37
at iterate (\node_modules\extdirect\lib\api.js:222:35)
at \node_modules\extdirect\lib\api.js:241:25
at FSReqWrap.oncomplete (fs.js:117:15)
Example API ad
module.exports = {
create(params, callback) {
},
read(params, callback) {
let data = [];
for (let i = 0; i < 10; i++) {
data.push({
id: i + 1,
title: `Запись номер ${i + 1}`
});
}
callback(null, {
total: data.length,
data: data
});
},
update(params, callback) {
},
destroy(params, callback) {
}
};
On line 117 regular expression should be corrected:
var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m,
As stated in 5.1 what's new:
"Full metadata support
One of the frequently requested features for Direct subsystem was support for passing metadata with CRUD operations in a Proxy. Previously this was implemented only for Read operations using extraParams property on the Proxy; unfortunately that approach made it near impossible to support CUD operations as well.
Starting with Ext JS 5.1, any Direct method invocation can be supplied with metadata that will be passed to the server side separately from method arguments. This feature is immediately available with Direct proxy as well via the new metadata property that can be used instead of extraParams with full range of CRUD operations."
http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/#!/api/Ext.data.proxy.Direct-cfg-metadata
More descriptive variable names and comments in router.js would be very helpful.
I am working on a system architecture document, part of which describes middleware, which uses nodejs.extdirect. Today I tried to correctly describe exception handling and method batching.
I have understood much of router.js a while ago. But this second time "what does this code do" makes me recognize the need for descriptive variable names in router.js and comments describing intent of loops, conditionals, etc. That will enable meaningful review of this package.
I think the original author should have a first go.
This might not be an Ext Direct issue, but it is definitely in the area. While I am working on a solution for our project, here for discussion:
Using Ext Direct to Node.js to MongoDB. A lot works well.
Then noticed round trip of dates isn't working right.
Have ISODate in database (from Date which was generate by Node.js). But after an update from client (sent via Ext Direct to Node.js to MongoDB) it is a string. That doesn't sort well.
Assuming you know JSON doesn't have built-in support for Date.
Obviously I could on the server per field convert the string to Date. Or in a generic way code for all fields whose name ends in _date to convert from string to Date.
But, did anyone find a way to fully automatically tag any Date from the client so when it travels to the server via Ext Direct so the server knows it is a Date?
Would that be a question of "clever use of JSON"? Another solution?
Any ideas?
I couldn't have figured out Ext Direct without you. After a few modifications, it's working beautifully. Are you running this under windows? When I ran your example, the module loader couldn't find the /direct folder. It kept looking for it under C:\direct
I think it's doing this because it installed as a global module. I don't know if this is a bug or not though.
Why does I get such an error message from node.js server?
It is generated in router.js line 43 . that means that so = d[i]; is undefined above.
In my direct POST the parameters are all set i.e.:
{"action":"DXFormTest","method":"testMe","data":[{"username":"fdgf","password":"fdgfd"}],"type":"rpc","tid":1}
Appreciating any hints.
It would be cool to have ts definition for direct configuration :)
Here is my own interface, but properties could be optional too :
export interface ExtDirectConfig {
/** Namespace in which server will be accessible from client side. Ex : 'Server' */
rootNamespace: string,
/** Support method discovery without `function` keyword. */
ES6: boolean,
/** API Name */
apiName: string,
/** URL to retrieve API configuration. Ex : '/directapi' */
apiUrl: string,
/** , URL to call Direct methods : ex "/direct" */
classRouteUrl: string
/** Direct class location in filesystem relative to the server directory : ex : '/direct', */
classPath: string,
/** Hosting server name. Ex : 'localhost' */
server: string,
/** Hosting server port. Ex : "3000" */
port: string,
protocol: 'http' | 'https',
/** Operation timeout. Default : 30000 */
timeout: number,
/** Set true to cache API's for production. During development setting to false will allow to make any changes and access API's without server reload */
cacheAPI: boolean,
/** Use relative URL's */
relativeUrl: boolean,
/** If true, will append req and res objects to method call */
appendRequestResponseObjects: boolean,
/** Metadata support */
enableMetadata: boolean,
/** Automatically append success true|false */
responseHelper: boolean,
/** Enable Helpers to have methods before and after API discovery as well as before and after Transaction batch */
enableProcessors: boolean
}
my api were working smothely but this morning when i started them i am getting this probleme with post and put this is my code could any one help me
var express = require('express');
var mongoose = require('mongoose');
var router = express.Router();
var Ligne = require('../models/Ligne');
var Client = require('../models/Client');
router.post('/addligne',function (req,res) {
var ligne = new Ligne();
ligne.num = req.body.num
ligne.operator = req.body.operator;
ligne.solde = req.body.solde;
ligne.code_puk= req.body.code_puk ;
ligne.code_pin= req.body.code_pin;
ligne.save(function(err) {
if (err) throw err ;
res.status(200);
res.json({
"resualt": " added"
});
console.log(" ligne added ")
});
})
router.post('/addclient', function (req,res) {
var client = new Client();
client.nom = req.body.nom;
client.prenom = req.body.prenom;
client.cin = req.body.cin ;
client.email = req.body.email;
client.date_naiss = req.body.date_naiss;
client.sexe = req.body.sexe;
client.ville = req.body.ville;
client.rue= req.body.rue;
client.code_postal= req.body.code_postal;
client.note = req.body.note ;
client.save(function (err) {
if (err) throw err ;
res.status(200);
res.json({
"resualt": "added"
})
console.log("ligne added")
})
})
router.post('/pushligne' , function (req,res) {
ligne.num = '55';
ligne.save(function(err) {
if (err) throw err ;
res.status(200);
res.json({
"resualt": " added"
});
console.log(" ligne added ")
});
})
router.put('/try', function (req,res) {
var ide = '5acb3edcf9f8061408510d6e';
Client.findOneAndUpdate({_id: ide},{$set: {sexe: 'hassan'}},
{safe: true, upsert: true, new: true},function (err,model) {
if (err) return res.status(500).send(err);
return res.send(Client);
})
})
module.exports = router;
Wrong url is computed at request /directapi
he file api.js need to fix the line 52:
'url': config.relativeUrl ? config.classPath : config.protocol + '://' + config.server + (config.port == '80' ? '' : (':' + config.port)) + config.classPath,
to
'url': config.relativeUrl ? config.classPath : config.protocol + '://' + config.server + (config.port == '80' ? '' : (':' + config.port)) + config.classRouteUrl,
Thanks for nice the module, am using in my project but i had to make a few changes in router.js
my version router.js
var vPath = require('path'),
route = exports;
route.processRoute = function(req, resp, path){
var root = process.env.PWD,
files = req.files,
data = req.body,
callback,
so,
upload = false,
d = [],
reduce,
rLen,
cp,
batch = [],
x,
i;
//process after we return from DX method
var finalCallback = function(batch){
var str = JSON.stringify(batch, 'utf8');
if(reduce === 0){
if (upload) {
resp.writeHead(200, {'Content-type': 'text/html'});
resp.end('<html><body><textarea>' + str + '</textarea></body></html>');
} else {
resp.writeHead(200, {'Content-type': 'application/json'});
resp.end(str);
}
}
};
if(data instanceof Array){
d = data;
}else{
d.push(data);
}
reduce = d.length;
try{
for(i = 0, rLen = d.length; i < rLen; i++){
so = d[i];
if (so.extAction) {
cp = copyObject(so);
so.action = so.extAction;
so.method = so.extMethod;
so.tid = so.extTID;
so.type = so.extType;
so.isUpload = upload = so.extUpload === "true";
delete cp.extAction;
delete cp.extType;
delete cp.extMethod;
delete cp.extTID;
delete cp.extUpload;
}
callback = function(so){
return function(err,result){
if(err)
{
var ebatch = so;
ebatch['type'] = 'exception';
ebatch['message'] = err.message;
if(global.DEBUG == true)
{
ebatch['where'] = err.stack;
}
batch.push(ebatch);
reduce--;
finalCallback(batch);
} else
{
var packet = {
type: 'rpc',
tid: so.tid,
action: so.action,
method: so.method,
result: result
};
batch.push(packet);
reduce--;
finalCallback(batch);
}
}
}.apply(null, [so]);
x = require(vPath.join(root, path, so.action));
if(!so.data){
so.data = [];
}
if(cp){
so.data.push(cp);
}
if(upload === true){
so.data.push(files);
}
so.data.push(callback);
//so.data.push(req); // Session support
x[so.method].apply({request : req, response : resp, session : req.session} , so.data);
}
}catch(e) {
var ebatch = so;
ebatch['type'] = 'exception';
ebatch['message'] = e.message;
if(global.DEBUG == true)
{
ebatch['where'] = e.stack;
}
var str = JSON.stringify(ebatch, 'utf8');
resp.writeHead(200, {'Content-type': 'application/json'});
resp.end(str);
//console.log(e);
}
};
function copyObject(obj) {
var newObj = {};
for (var key in obj) {
newObj[key] = obj[key];
}
return newObj;
}
I'm trying to replicate the example in the readme. I think I have found a bug in this Node Ext.Direct implementation which occurs when the Sencha Touch 2 client is not in the same location as the node server.
After I try and call my client function to execute a server call(ie. ExtRemote.DXTest.testMe()), I get the following error in Web Inspector for my app:
file://localhost/direct?_dc=1376962496490
What I believe is happening here is that /directapi is returning the wrong url value since it assumes the client and node server are in the same location. Attempts to fix it so that it returns the correct url in the following way results in an error:
app.get('/directapi', function(request, response) {
var api = extdirect.getAPI(EXTDIRECT_NAMESPACE, EXTDIRECT_API_NAME, 'http://localhost:3000'+EXTDIRECT_PATH,
EXTDIRECT_PREFIX);
response.writeHead(200, {'Content-Type': 'application/json'});
response.end(api);
});
Here is the error:
Error: ENOENT, no such file or directory '/Users/user/projects/Network/server/NodeServer/http:/localhost:3000/direct'
Please share option "classPath" on "classPath" and "classUrl", does not always correspond to the physical location of the folder path RL. For example I have it so: "classUrl": "/ direct",
"classPath": "/ app / direct"
Jurisv,
I have been using you direct example for awhile and it is great. I recently upgraded an extjs 5.1.0 project using direct to extjs 6.5.0. I also upgraded my extjs direct node server from 1.0 to your new 2.0 version. I do see that your version says extjs 5. I was hoping to use it with the latest extjs.
In the directapi string that returns from the server I am getting this error:
Uncaught TypeError: Ext.namespace is not a function
at directapi: 1
Any suggestions you can give me would be greatly appreciated.
Thanks
I'm wondering what is the purpose of the prefix in the config.json file. I see that you can prefix your api's in the direct folder, but is this sort of thing needed? Hopefully you can clarify this as it isn't really mentioned in the docs.. thanks!
Oops, wrong project. Should be in extdirect.examples.
You probably know this kind of situation, so I'll keep it short: Apparently at time of autoLoad the DirectAPI isn't available yet, so it fails (nasty stuff in console log saying can't do that API), and the spinning Loading indicator prevents anything from being done in UI. After I switched off (got rid of) autoLoad for Tasks store there was no more nasties in console log, no more spinning Loading indicator, and I was able to click Add Task and add a task, which I then saw in MongoDB. Obviously though didn't load existing data on startup, but you probably know where you want to trigger that (what event).
Hi,
If the application is started by some other process than node (Passenger, for example), the processRoute will return an invalid route.
var route = {
processRoute : function(req, resp, config){
var root = vPath.dirname(process.mainModule.filename),
The problem is process.mainModule.filename
.
Not only in development but possibly in production too clients will get to server in different way, at different URLs. Might be multiple servers, might be from different networks hence different IP numbers.
The classPath itself would be what we'd want given as url in the API, not a specific server.
In api.js createCachedAPI currently code does
"url": config.protocol + '://' + config.server + (config.port == '80' ? '' : (':'+ config.port))+ config.classPath,
and I think there should be an option if all of protocol, server, and port are falsy (empty string, null, undefine) then it should merely be
"url": config.classPath,
Meanwhile I am looking how to patch that after getting it with protocol://server:port in an Architect project.
sort[0].property, sort[0].direction, start and limit variables can all be exploited.
Other Id values also need to be escaped.
var s = params.sort[0];
sql = sql + ' order by ' + s.property + ' ' + s.direction;
sql = sql + ' limit ' + params.start + ' , ' + params.limit;
Hello Juris,
For the fist time (I use Ext.Direct since 2 years), I run into this strange error when the api is called, after having added a new module in direct/ folder :
Fri, 08 Sep 2017 09:13:48 GMT : exception non gérée récupérée dans server.js
Cannot read property '1' of null
TypeError: Cannot read property '1' of null
at API.reflection (C:\node-projects\payroll-app\node_modules\extdirect\lib\api.js:196:28)
at C:\node-projects\payroll-app\node_modules\extdirect\lib\api.js:85:37
at iterate (C:\node-projects\payroll-app\node_modules\extdirect\lib\api.js:224:35)
at C:\node-projects\payroll-app\node_modules\extdirect\lib\api.js:243:25
at FSReqWrap.oncomplete (fs.js:153:5)
the culprit is argDecl there :
Lines 189 to 192 in f00a4b3
I don't understand the reason, because this module is seemingly written like my other direct modules :
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
require("source-map-support/register");
const async = require("async");
const tools = require("../../tools");
const selectPERIA_1 = require("../../payrollEngine/selectPERIA");
const getPosConv_1 = require("../../payrollEngine/getPosConv");
const db_1 = require("../../db");
const sql_template_strings_2 = require("sql-template-strings");
const self = {
get: function (params, externalCallback) {
//@meta _config _appSessionId
async.waterfall([
(cb) => self.selectData(params, cb)
], (err, rows) => {
if (err) {
tools.logError("settingsPortalEmployee.get() : erreur : ", err);
return externalCallback({
message: err.message,
where: err.message
});
}
return externalCallback(null, {
success: true,
data: rows
});
});
},
selectData: function (params, done) {
async.waterfall([
(cb) => {
db_1.default.connect((errConnect, client) => {
return cb(errConnect, client);
});
},
(client, cb) => self.selectCnt(params.uti_id, client, cb),
(client, cnt, cb) => {
selectPERIA_1.default.get(client, cnt, (errPeria, dataPeria) => {
return cb(errPeria, client, cnt, dataPeria);
});
},
(client, cnt, dataPeria, cb) => {
getPosConv_1.default.process(client, cnt, cnt.peri_anneemoi, (errPosConv, posConv) => {
return cb(errPosConv, client, cnt, dataPeria, posConv);
});
}
], function (err, results) {
if (err) {
return done(err);
}
return done(null, results);
});
},
/**
* Renvoit le dernier contrat du salarié correspondant à l'utilisateur
*/
selectCnt: (uti_id, client, done) => {
const sql = sql_template_strings_2.default `
SELECT
cnt.cnt_id,
sal.pad_id,
cnt.ncnt_id,
cnt.semp_id,
cnt.eta_id,
cnt.cnt_fin_date,
ppa_cour.peri_anneemois
FROM
pay_contrat_cnt cnt INNER JOIN pay_salarie_sal sal ON cnt.sal_id = sal.sal_id
INNER JOIN usr_utilisateur_uti uti ON sal.sal_id = uti.sal_id
INNER JOIN pay_lotdepaye_lot lot ON cnt.lot_id = lot.lot_id
LEFT OUTER JOIN pay_periodepaye_ppa ppa_cour ON lot.ppa_id_courante = ppa_cour.ppa_id
WHERE
uti.uti_id = ${uti_id}
ORDER BY
cnt.cnt_fin_date DESC
`;
client.query(sql, (err, result) => {
if (err) {
return done(err);
}
return done(null, client, result.rows[0]);
});
}
};
module.exports = self;
//# sourceMappingURL=settingsPortalEmployee.js.map
any idea of the cause ?
hi,
i discovered the following problem:
on any exception (e.g. mysql) in direct methods the process/server dies.
i think the catch in lib/router.js (line 100) will never catch an exception, because the direct function is executed asynchronously. => the exception is throw outside/after the try/catch.
i'm not sure if i miss something. some help would be wonderful ;).
mithrandir
Replace dots in classpath - router.js
apiPath = vPath.join(root, config.classPath, currentPacket.action.replace('.', slash)) + '.js';
to
apiPath = vPath.join(root, config.classPath, currentPacket.action.replace(/\./g, slash)) + '.js';
Connect/Express has some great support for CSRF protection. Ideally it should be baked into both extdirect library and the Sencha example client code.
This will then encourage Sencha devs using this kit to get the security right.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.