@sap/cds 1.15.1 → 1.18.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cds.js CHANGED
@@ -1,76 +1,79 @@
1
- var async = require('async');
2
-
3
- var metadata = require('./metadata');
4
- var manager = require('./manager');
5
- var queries = require("./cds-queries");
6
- var SqlQuery = queries.Query;
7
- var transaction = require('./transaction');
1
+ const async = require('async');
8
2
 
3
+ const metadata = require('./metadata');
4
+ const manager = require('./manager');
5
+ const queries = require('./cds-queries');
6
+ const SqlQuery = queries.Query;
7
+ const transaction = require('./transaction');
8
+ const _hdbext = require('./_hdbext');
9
9
 
10
10
  // transactions
11
11
 
12
12
  // returns connected DB client
13
- exports.$getTransaction = function (dbconn, callback) {
14
- if (typeof callback === "undefined") {
15
- callback = dbconn;
16
- dbconn = null;
13
+ exports.$getTransaction = function(dbconn, callback) {
14
+ if (typeof callback === 'undefined') {
15
+ callback = dbconn;
16
+ dbconn = null;
17
+ }
18
+ transaction.getClient(dbconn, function(err, client) {
19
+ if (err) {
20
+ return callback(err);
17
21
  }
18
- transaction.getClient(dbconn, function(err, client) {
19
- if (err)
20
- return callback(err);
21
- client.$get = function (entity, key, callback) {
22
- manager._get(client, entity, key, callback);
23
- };
24
- client.$find = function (entity, condition, callback) {
25
- manager._find(client, entity, condition, callback);
26
- };
27
- client.$save = function (instance, callback) {
28
- manager._save(client, instance, callback);
29
- };
30
- client.$discard = function (instance, callback) {
31
- manager._discard(client, instance, callback);
32
- };
33
- client.$getAll = function (refs, callback) {
34
- var getter = function (ref, cb) {
35
- manager._get(client, ref.$entity, ref, cb);
36
- };
37
- async.map(refs, getter, callback);
38
- };
39
- client.$findAll = function (refs, callback) {
40
- var finder = function (ref, cb) {
41
- manager._find(client, ref.$entity, ref, cb);
42
- };
43
- async.map(refs, finder, callback);
44
- };
45
- client.$saveAll = function (refs, callback) {
46
- var saver = function(ref, cb) {
47
- manager._save(client, ref, cb);
48
- };
49
- async.map(refs, saver, callback);
50
- };
51
- client.$discardAll = function (refs, callback) {
52
- var discarder = function(ref, cb) {
53
- manager._discard(client, ref, cb);
54
- };
55
- async.map(refs, discarder, function(err) { callback(err); });
56
- };
57
- client.$delete = function(entity, condition, callback) {
58
- manager._delete(client, entity, condition, callback);
59
- };
60
- client.$setAutoCommit = function (auto) {
61
- transaction._autoCommit(client, auto);
62
- };
63
- client.$commit = function (callback) {
64
- transaction._commit(client, callback);
65
- };
66
- client.$rollback = function (callback) {
67
- transaction._rollback(client, callback);
68
- };
69
- client.$close = function() {
70
- transaction.releaseClient(client, dbconn);
71
- };
72
- callback(err, client);
73
- });
22
+ client.$get = function(entity, key, callback) {
23
+ manager._get(client, entity, key, callback);
24
+ };
25
+ client.$find = function(entity, condition, callback) {
26
+ manager._find(client, entity, condition, callback);
27
+ };
28
+ client.$save = function(instance, callback) {
29
+ manager._save(client, instance, callback);
30
+ };
31
+ client.$discard = function(instance, callback) {
32
+ manager._discard(client, instance, callback);
33
+ };
34
+ client.$getAll = function(refs, callback) {
35
+ const getter = function(ref, cb) {
36
+ manager._get(client, ref.$entity, ref, cb);
37
+ };
38
+ async.map(refs, getter, callback);
39
+ };
40
+ client.$findAll = function(refs, callback) {
41
+ const finder = function(ref, cb) {
42
+ manager._find(client, ref.$entity, ref, cb);
43
+ };
44
+ async.map(refs, finder, callback);
45
+ };
46
+ client.$saveAll = function(refs, callback) {
47
+ const saver = function(ref, cb) {
48
+ manager._save(client, ref, cb);
49
+ };
50
+ async.map(refs, saver, callback);
51
+ };
52
+ client.$discardAll = function(refs, callback) {
53
+ const discarder = function(ref, cb) {
54
+ manager._discard(client, ref, cb);
55
+ };
56
+ async.map(refs, discarder, function(err) {
57
+ callback(err);
58
+ });
59
+ };
60
+ client.$delete = function(entity, condition, callback) {
61
+ manager._delete(client, entity, condition, callback);
62
+ };
63
+ client.$setAutoCommit = function(auto) {
64
+ transaction._autoCommit(client, auto);
65
+ };
66
+ client.$commit = function(callback) {
67
+ transaction._commit(client, callback);
68
+ };
69
+ client.$rollback = function(callback) {
70
+ transaction._rollback(client, callback);
71
+ };
72
+ client.$close = function() {
73
+ transaction.releaseClient(client, dbconn);
74
+ };
75
+ callback(err, client);
76
+ });
74
77
  };
75
78
 
76
79
 
@@ -78,55 +81,57 @@ exports.$getTransaction = function (dbconn, callback) {
78
81
 
79
82
  // batch-import (main API function)
80
83
  exports.$importEntities = function(refs, opts, callback) {
81
- if (typeof callback === "undefined") {
82
- callback = opts;
83
- opts = {};
84
+ if (typeof callback === 'undefined') {
85
+ callback = opts;
86
+ opts = {};
87
+ }
88
+ metadata._import(refs, opts, function(error, entities) {
89
+ for (const name in entities) {
90
+ if (entities[name]) {
91
+ addXSInterface(entities[name]);
92
+ }
84
93
  }
85
- metadata._import(refs, opts, function (error, entities) {
86
- for (var name in entities)
87
- if (entities[name])
88
- addXSInterface(entities[name]);
89
- callback(error, entities);
90
- });
91
- }
94
+ callback(error, entities);
95
+ });
96
+ };
92
97
 
93
98
  exports.$importEntity = function(ref, callback) {
94
- exports.$importEntities([ref], callback);
99
+ exports.$importEntities([ref], callback);
95
100
  };
96
101
 
97
102
  // (async) retrieve entity object by name
98
103
  // NOTE: callback will never be invoked if entity is not imported!
99
104
  exports.$getEntity = function(entityName, callback) {
100
- metadata.getEntity(entityName, callback);
105
+ metadata.getEntity(entityName, callback);
101
106
  };
102
107
  exports.$getEntities = function(entityNames, callback) {
103
- var getter = function (name, cb) {
104
- exports.$getEntity(name, cb);
105
- };
106
- async.map(entityNames, getter, callback);
108
+ const getter = function(name, cb) {
109
+ exports.$getEntity(name, cb);
110
+ };
111
+ async.map(entityNames, getter, callback);
107
112
  };
108
113
 
109
114
  // retrieve entity object by name
110
115
  // NOTE: returns null if entity import has not completed yet
111
116
  exports.$getEntitySync = function(entityName) {
112
- return metadata.getEntitySync(entityName);
117
+ return metadata.getEntitySync(entityName);
113
118
  };
114
119
 
115
120
 
116
121
  // instance management
117
122
 
118
123
  function addXSInterface(entity) {
119
- // batch operations
120
- entity.$prepare = function(value) {
121
- value.$entity = entity;
122
- return value;
123
- };
124
- // general queries
125
- entity.$query = function(client) {
126
- var param = {};
127
- param["t0"] = { entity: entity };
128
- return new SqlQuery(client, param);
129
- };
124
+ // batch operations
125
+ entity.$prepare = function(value) {
126
+ value.$entity = entity;
127
+ return value;
128
+ };
129
+ // general queries
130
+ entity.$query = function(client) {
131
+ const param = {};
132
+ param['t0'] = {entity: entity};
133
+ return new SqlQuery(client, param);
134
+ };
130
135
  }
131
136
 
132
137
 
@@ -141,7 +146,7 @@ exports._clearImports = metadata._clearImports;
141
146
  exports.Query = SqlQuery;
142
147
  exports.createQuery = queries.createQuery;
143
148
  exports.$par = function(id) {
144
- return new queries.Par(id);
149
+ return new queries.Par(id);
145
150
  };
146
151
 
147
152
 
@@ -154,12 +159,14 @@ exports.save = exports.$save;
154
159
  exports.queries = queries;
155
160
  exports.extensionPoints = manager.extensionPoints; // hook for extenders
156
161
  exports.xsjs = function(conn, callback) {
157
- exports.$getTransaction(conn._client, function(err, tx) {
158
- if (err) {
159
- callback(err);
160
- } else {
161
- var xsjscds = require("./xsjs-cds").init(tx);
162
- callback(null, xsjscds);
163
- }
164
- });
162
+ exports.$getTransaction(conn._client, function(err, tx) {
163
+ if (err) {
164
+ callback(err);
165
+ } else {
166
+ const xsjscds = require('./xsjs-cds').init(tx);
167
+ callback(null, xsjscds);
168
+ }
169
+ });
165
170
  }.sync;
171
+ // Use at your own risk, middleware comes from @sap/hdbext@^4
172
+ exports.middleware = _hdbext.middleware;
package/exprs.js CHANGED
@@ -1,142 +1,153 @@
1
- var utils = require('./utils');
1
+ const utils = require('./utils');
2
2
 
3
3
 
4
4
  // NOTE: function raises exception in case of invalid expression
5
5
  exports.buildInstanceFilter = function(entity, condition) {
6
- return function(instance) {
7
- return evalExpression(entity, condition, instance);
8
- };
6
+ return function(instance) {
7
+ return evalExpression(entity, condition, instance);
8
+ };
9
9
  };
10
10
 
11
11
 
12
12
  // check if given instance matches property criteria
13
13
  function evalExpression(entity, criteria, instance) {
14
- var realcrit = criteria.$eq || criteria.$ne || criteria;
15
- var match = true;
16
- utils.forInstance(realcrit, entity.$_mapping, {
17
- $column: function(p, f, v, m) {
18
- if (v === null || typeof v[f] === "undefined")
19
- return; // property not part of criteria
20
- var value = utils.getPropPath(instance, p + f);
21
- if (!evalCondition(v[f], value))
22
- match = false;
23
- },
24
- $association: function(p, f, v, m) {
25
- if (v === null || typeof v[f] === "undefined")
26
- return; // property not part of criteria
27
- var value = utils.getPropPath(instance, p + f);
28
- // empty association
29
- if (v[f] === null) { // short for { $none: true }
30
- match = match && !value;
31
- return;
32
- } else if ("$none" in v[f]) {
33
- match = match && (v[f].$none && isnone(value) || !v[f].$none && !isnone(value));
34
- return;
35
- } else if ("$empty" in v[f]) { // deprecated for "$none"
36
- match = match && (v[f].$empty && isnone(value) || !v[f].$empty && !isnone(value));
37
- return;
38
- } else if ("$null" in v[f]) {
39
- throw new Error("invalid $null operator on association");
40
- } else if (!value) {
41
- match = match && (v[f].$none || v[f].$empty);
42
- return;
43
- }
44
- // non-empty association
45
- if (utils.isArray(value))
46
- throw new Error("invalid navigation in expression");
47
- if (!("$_entity" in value))
48
- throw new Error("*** ASSERT FAIL *** comparing against non-instance");
49
- if ("$_entity" in v[f]) {
50
- // shortcut for comparing two instances
51
- if (v[f] === value)
52
- return; // found match --> keep match unchanged
53
- } else {
54
- // follow association recursively
55
- if (evalExpression(m[f].$association.$class, v[f], value))
56
- return; // found match --> keep match unchanged
57
- }
58
- match = false;
59
- }
60
- });
61
- return "$ne" in criteria ? !match : match;
14
+ const realcrit = criteria.$eq || criteria.$ne || criteria;
15
+ let match = true;
16
+ utils.forInstance(realcrit, entity.$_mapping, {
17
+ $column: function(p, f, v, m) {
18
+ if (v === null || typeof v[f] === 'undefined') {
19
+ return;
20
+ } // property not part of criteria
21
+ const value = utils.getPropPath(instance, p + f);
22
+ if (!evalCondition(v[f], value)) {
23
+ match = false;
24
+ }
25
+ },
26
+ $association: function(p, f, v, m) {
27
+ if (v === null || typeof v[f] === 'undefined') {
28
+ return;
29
+ } // property not part of criteria
30
+ const value = utils.getPropPath(instance, p + f);
31
+ // empty association
32
+ if (v[f] === null) { // short for { $none: true }
33
+ match = match && !value;
34
+ return;
35
+ } else if ('$none' in v[f]) {
36
+ match = match && (v[f].$none && isnone(value) || !v[f].$none && !isnone(value));
37
+ return;
38
+ } else if ('$empty' in v[f]) { // deprecated for "$none"
39
+ match = match && (v[f].$empty && isnone(value) || !v[f].$empty && !isnone(value));
40
+ return;
41
+ } else if ('$null' in v[f]) {
42
+ throw new Error('invalid $null operator on association');
43
+ } else if (!value) {
44
+ match = match && (v[f].$none || v[f].$empty);
45
+ return;
46
+ }
47
+ // non-empty association
48
+ if (utils.isArray(value)) {
49
+ throw new Error('invalid navigation in expression');
50
+ }
51
+ if (!('$_entity' in value)) {
52
+ throw new Error('*** ASSERT FAIL *** comparing against non-instance');
53
+ }
54
+ if ('$_entity' in v[f]) {
55
+ // shortcut for comparing two instances
56
+ if (v[f] === value) {
57
+ return;
58
+ } // found match --> keep match unchanged
59
+ } else {
60
+ // follow association recursively
61
+ if (evalExpression(m[f].$association.$class, v[f], value)) {
62
+ return;
63
+ } // found match --> keep match unchanged
64
+ }
65
+ match = false;
66
+ },
67
+ });
68
+ return '$ne' in criteria ? !match : match;
62
69
  }
63
70
 
64
71
 
65
72
  // evaluate condition for property value
66
- var evalCondition = function(condition, value) {
67
- // condition === expr
68
- if (typeof condition !== 'object')
69
- // NOTE: direct comparison between objects is always a bad idea
70
- return defaultCompare(value, condition) === 0;
73
+ const evalCondition = function(condition, value) {
74
+ // condition === expr
75
+ // NOTE: direct comparison between objects is always a bad idea
76
+ if (typeof condition !== 'object') {
77
+ return defaultCompare(value, condition) === 0;
78
+ }
71
79
 
72
- // use user-supplied comparison function?
73
- var compare = "$using" in condition ? condition.$using : defaultCompare;
80
+ // use user-supplied comparison function?
81
+ const compare = '$using' in condition ? condition.$using : defaultCompare;
74
82
 
75
- // condition === { op: expr, op: expr, ... }
76
- for (var op in condition) {
77
- var expr = condition[op];
78
- switch (op) {
79
- // NOTE: using !(...) to handle "undefined" values
80
- case "$using":
81
- break; // skip comparison function
82
- case "$eq":
83
- if (!(compare(value, expr) === 0)) return false;
84
- break;
85
- case "$ne":
86
- var res = compare(value, expr);
87
- if (!(res < 0 || res > 0)) return false;
88
- break;
89
- case "$lt":
90
- if (!(compare(value, expr) < 0)) return false;
91
- break;
92
- case "$le":
93
- if (!(compare(value, expr) <= 0)) return false;
94
- break;
95
- case "$gt":
96
- if (!(compare(value, expr) > 0)) return false;
97
- break;
98
- case "$ge":
99
- if (!(compare(value, expr) >= 0)) return false;
100
- break;
101
- case "$like":
102
- if (!islike(expr, value)) return false;
103
- break;
104
- case "$unlike":
105
- if (islike(expr, value) || typeof value === "undefined") return false;
106
- break;
107
- case "$null":
108
- if (!(isnull(value) && expr || !isnull(value) && !expr)) return false;
109
- break;
110
- case "$empty":
111
- throw new Error("invalid $empty operator on non-association");
112
- case "$none":
113
- throw new Error("invalid $none operator on non-association");
114
- default:
115
- throw new Error("invalid expression operator: " + op);
116
- }
83
+ // condition === { op: expr, op: expr, ... }
84
+ for (const op in condition) {
85
+ const expr = condition[op];
86
+ switch (op) {
87
+ // NOTE: using !(...) to handle "undefined" values
88
+ case '$using':
89
+ break; // skip comparison function
90
+ case '$eq':
91
+ if (!(compare(value, expr) === 0)) return false;
92
+ break;
93
+ case '$ne':
94
+ const res = compare(value, expr);
95
+ if (!(res < 0 || res > 0)) return false;
96
+ break;
97
+ case '$lt':
98
+ if (!(compare(value, expr) < 0)) return false;
99
+ break;
100
+ case '$le':
101
+ if (!(compare(value, expr) <= 0)) return false;
102
+ break;
103
+ case '$gt':
104
+ if (!(compare(value, expr) > 0)) return false;
105
+ break;
106
+ case '$ge':
107
+ if (!(compare(value, expr) >= 0)) return false;
108
+ break;
109
+ case '$like':
110
+ if (!islike(expr, value)) return false;
111
+ break;
112
+ case '$unlike':
113
+ if (islike(expr, value) || typeof value === 'undefined') return false;
114
+ break;
115
+ case '$null':
116
+ if (!(isnull(value) && expr || !isnull(value) && !expr)) return false;
117
+ break;
118
+ case '$empty':
119
+ throw new Error('invalid $empty operator on non-association');
120
+ case '$none':
121
+ throw new Error('invalid $none operator on non-association');
122
+ default:
123
+ throw new Error(`invalid expression operator: ${ op}`);
117
124
  }
118
- return true;
125
+ }
126
+ return true;
119
127
  };
120
128
 
121
129
 
122
130
  // compare two primitive values semantically
123
131
  function defaultCompare(lhs, rhs) {
124
- return lhs < rhs ? -1 : lhs > rhs ? +1 : lhs == rhs ? 0 : undefined;
132
+ return lhs < rhs ? -1 : lhs > rhs ? +1 : lhs == rhs ? 0 : undefined;
125
133
  };
126
134
 
127
135
 
128
136
  // convert SQL LIKE pattern to regular expression
129
137
  function islike(pattern, value) {
130
- var escaped = pattern.replace(/[-\\.^$*+?()|[\]{}]/g, '\\$&').replace(/%/g, ".*").replace(/_/g, ".");
131
- return (new RegExp(escaped)).test(value);
138
+ const escaped = pattern
139
+ .replace(/[-\\.^$*+?()|[\]{}]/g, '\\$&')
140
+ .replace(/%/g, '.*')
141
+ .replace(/_/g, '.');
142
+ return (new RegExp(escaped)).test(value);
132
143
  }
133
144
 
134
145
  // check for NULL value; includes JavaScript null for associations
135
146
  function isnull(value) {
136
- return typeof value === "undefined" || value === null;
147
+ return typeof value === 'undefined' || value === null;
137
148
  }
138
149
 
139
150
  // check if target instance(s) exist
140
151
  function isnone(value) {
141
- return isnull(value) || utils.isArray(value) && value.length === 0;
152
+ return isnull(value) || utils.isArray(value) && value.length === 0;
142
153
  }