@sap/cds 7.3.1 → 7.4.0
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/CHANGELOG.md +58 -3
- package/_i18n/i18n_es_MX.properties +110 -0
- package/apis/cds.d.ts +13 -12
- package/apis/core.d.ts +27 -108
- package/apis/cqn.d.ts +15 -18
- package/apis/csn.d.ts +95 -60
- package/apis/env.d.ts +25 -0
- package/apis/events.d.ts +124 -0
- package/apis/{reflect.d.ts → linked.d.ts} +27 -38
- package/apis/models.d.ts +60 -45
- package/apis/ql.d.ts +11 -5
- package/apis/{serve.d.ts → server.d.ts} +57 -31
- package/apis/services.d.ts +74 -145
- package/apis/test.d.ts +1 -1
- package/bin/serve.js +3 -0
- package/lib/compile/cds-compile.js +2 -2
- package/lib/compile/to/edm.js +8 -3
- package/lib/compile/to/gql.js +4 -0
- package/lib/dbs/cds-deploy.js +52 -4
- package/lib/env/cds-requires.js +27 -15
- package/lib/env/defaults.js +1 -0
- package/lib/env/schemas/index.js +10 -0
- package/lib/index.js +7 -4
- package/lib/linked/models.js +8 -5
- package/lib/ql/CREATE.js +2 -0
- package/lib/ql/DELETE.js +1 -0
- package/lib/ql/DROP.js +2 -0
- package/lib/ql/INSERT.js +2 -22
- package/lib/ql/Query.js +59 -22
- package/lib/ql/SELECT.js +5 -0
- package/lib/ql/STREAM.js +2 -0
- package/lib/ql/UPDATE.js +2 -0
- package/lib/ql/UPSERT.js +3 -1
- package/lib/ql/cds-ql.js +21 -5
- package/lib/ql/infer.js +129 -0
- package/lib/req/cds-context.js +8 -5
- package/lib/srv/cds-connect.js +3 -1
- package/lib/utils/axios.js +4 -2
- package/lib/utils/data.js +3 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/error.js +12 -0
- package/libx/_runtime/cds-services/adapter/odata-v4/handlers/metadata.js +26 -8
- package/libx/_runtime/cds-services/adapter/odata-v4/okra/odata-server/batch/BatchProcessor.js +1 -1
- package/libx/_runtime/cds-services/adapter/odata-v4/utils/data.js +11 -8
- package/libx/_runtime/common/code-ext/worker.js +5 -16
- package/libx/_runtime/common/generic/auth/capabilities.js +11 -2
- package/libx/_runtime/common/i18n/messages.properties +1 -0
- package/libx/_runtime/common/utils/postProcessing.js +1 -1
- package/libx/_runtime/common/utils/resolveView.js +20 -1
- package/libx/{common → _runtime/common}/utils/ucsn.js +19 -11
- package/libx/_runtime/db/expand/expandCQNToJoin.js +2 -2
- package/libx/_runtime/db/sql-builder/InsertBuilder.js +6 -1
- package/libx/_runtime/db/sql-builder/UpdateBuilder.js +6 -1
- package/libx/_runtime/db/sql-builder/dollar.js +7 -7
- package/libx/_runtime/fiori/generic/activate.js +2 -2
- package/libx/_runtime/fiori/generic/edit.js +25 -45
- package/libx/_runtime/fiori/generic/read.js +3 -5
- package/libx/_runtime/fiori/lean-draft.js +142 -64
- package/libx/_runtime/fiori/utils/delete.js +7 -1
- package/libx/_runtime/fiori/utils/handler.js +4 -6
- package/libx/_runtime/fiori/utils/lockInfo.js +27 -0
- package/libx/_runtime/fiori/utils/where.js +20 -1
- package/libx/_runtime/messaging/AMQPWebhookMessaging.js +3 -2
- package/libx/_runtime/messaging/Outbox.js +12 -47
- package/libx/_runtime/messaging/common-utils/AMQPClient.js +1 -3
- package/libx/_runtime/messaging/common-utils/authorizedRequest.js +3 -0
- package/libx/_runtime/messaging/common-utils/connections.js +1 -1
- package/libx/_runtime/messaging/enterprise-messaging.js +12 -13
- package/libx/_runtime/messaging/file-based.js +7 -5
- package/libx/_runtime/messaging/redis-messaging.js +10 -11
- package/libx/_runtime/messaging/service.js +12 -26
- package/libx/_runtime/remote/Service.js +52 -36
- package/libx/_runtime/remote/utils/client.js +22 -123
- package/libx/odata/afterburner.js +14 -5
- package/libx/odata/grammar.peggy +26 -7
- package/libx/odata/metadata.js +18 -1
- package/libx/odata/parser.js +1 -1
- package/libx/odata/service-document.js +0 -1
- package/libx/odata/utils.js +19 -3
- package/libx/{_runtime/messaging/outbox/utils.js → outbox/index.js} +94 -24
- package/libx/rest/middleware/parse.js +1 -1
- package/package.json +2 -2
- package/apis/connect.d.ts +0 -39
- package/bin/utils/modules.js +0 -7
- package/bin/utils/term.js +0 -56
- package/lib/env/schema.js +0 -9
- package/lib/linked/queries.js +0 -41
- package/lib/srv/protocols/odata-v2-proxy.js +0 -3699
- package/libx/common/asserts.js +0 -0
- package/libx/common/crud.js +0 -0
- package/libx/common/etag.js +0 -0
- package/libx/common/localized.js +0 -0
- package/libx/common/managed.js +0 -0
- package/libx/common/paging.js +0 -0
- package/libx/common/readme.md +0 -4
- package/libx/common/sorting.js +0 -0
- package/libx/common/temporal.js +0 -0
- package/libx/connect/auth.js +0 -0
- package/libx/connect/perf.js +0 -0
- package/libx/connect/readme.md +0 -3
- package/libx/fiori/draft/readme.md +0 -1
- package/libx/fiori/readme.md +0 -1
- package/libx/hana/readme.md +0 -1
- package/libx/msg/readme.md +0 -3
- package/libx/readme.md +0 -1
- package/libx/sqlite/readme.md +0 -1
- /package/libx/_runtime/{messaging/common-utils → common/utils}/waitingTime.js +0 -0
- /package/libx/{_runtime/messaging/outbox → outbox}/OutboxRunner.js +0 -0
|
@@ -1,19 +1,17 @@
|
|
|
1
|
-
const cds = require('
|
|
2
|
-
const waitingTime = require('../common-utils/waitingTime')
|
|
3
|
-
const OutboxRunner = require('./OutboxRunner')
|
|
4
|
-
const { isStandardError } = require('../../common/error/standardError')
|
|
1
|
+
const cds = require('../_runtime/cds')
|
|
5
2
|
const LOG = cds.log('persistent-outbox')
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
} catch (_e) {
|
|
11
|
-
// Don't throw
|
|
12
|
-
}
|
|
13
|
-
}
|
|
3
|
+
|
|
4
|
+
const { inspect } = require('util')
|
|
5
|
+
|
|
6
|
+
const OutboxRunner = require('./OutboxRunner')
|
|
14
7
|
const outboxRunner = new OutboxRunner()
|
|
8
|
+
|
|
9
|
+
const waitingTime = require('../_runtime/common/utils/waitingTime')
|
|
10
|
+
const { isStandardError } = require('../_runtime/common/error/standardError')
|
|
11
|
+
|
|
15
12
|
const cdsUser = 'cds.internal.user'
|
|
16
|
-
const messageProcessorRegistered = Symbol('message processor registered')
|
|
13
|
+
const $messageProcessorRegistered = Symbol('message processor registered')
|
|
14
|
+
const $outboxed = Symbol('outboxed')
|
|
17
15
|
|
|
18
16
|
const _get100NanosecondTimestampISOString = () => {
|
|
19
17
|
const [now, nanoseconds] = [new Date(), process.hrtime()[1]]
|
|
@@ -33,10 +31,8 @@ const _getMessagesEntity = () => {
|
|
|
33
31
|
const _isProviderTenant = tenant =>
|
|
34
32
|
cds.requires.auth && cds.requires.auth.credentials && cds.requires.auth.credentials.identityzoneid === tenant
|
|
35
33
|
|
|
36
|
-
const hasPersistentOutbox =
|
|
34
|
+
const hasPersistentOutbox = tenant => {
|
|
37
35
|
if (!cds.requires.outbox || cds.requires.outbox.kind !== 'persistent-outbox') return false
|
|
38
|
-
if (srv.options && srv.options.outbox && srv.options.outbox.kind && srv.options.outbox.kind !== 'persistent-outbox')
|
|
39
|
-
return false
|
|
40
36
|
if (cds.requires.multitenancy && tenant && _isProviderTenant(tenant)) return false // no persistence for provider account
|
|
41
37
|
return true
|
|
42
38
|
}
|
|
@@ -91,6 +87,14 @@ const processDefault = async (messages, { toBeDeleted, toBeUpdated, options, ser
|
|
|
91
87
|
}
|
|
92
88
|
}
|
|
93
89
|
|
|
90
|
+
const _safeJSONParse = string => {
|
|
91
|
+
try {
|
|
92
|
+
return string && JSON.parse(string)
|
|
93
|
+
} catch (_e) {
|
|
94
|
+
// Don't throw
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
94
98
|
// Note: This function can also run for each tenant on startup
|
|
95
99
|
const processMessages = async (service, tenant, _opts = {}) => {
|
|
96
100
|
const opts = Object.assign({ attempt: 0 }, _opts)
|
|
@@ -127,8 +131,11 @@ const processMessages = async (service, tenant, _opts = {}) => {
|
|
|
127
131
|
let currMaxAttempts = 0
|
|
128
132
|
const messagesGen = function* () {
|
|
129
133
|
for (const _message of messages) {
|
|
130
|
-
const
|
|
131
|
-
const userId =
|
|
134
|
+
const _msg = _safeJSONParse(_message.msg)
|
|
135
|
+
const userId = _msg[cdsUser]
|
|
136
|
+
const msg = _msg._fromSend ? new cds.Request(_msg) : new cds.Event(_msg)
|
|
137
|
+
delete msg._fromSend
|
|
138
|
+
Object.defineProperty(msg, '_fromOutbox', { value: true, enumerable: false })
|
|
132
139
|
delete msg[cdsUser]
|
|
133
140
|
currMaxAttempts = Math.max(_message.attempts || 0, currMaxAttempts)
|
|
134
141
|
const user = new cds.User.Privileged(userId)
|
|
@@ -137,7 +144,7 @@ const processMessages = async (service, tenant, _opts = {}) => {
|
|
|
137
144
|
process: () =>
|
|
138
145
|
cds._context.run({ user, tenant }, async () => {
|
|
139
146
|
try {
|
|
140
|
-
return
|
|
147
|
+
return await service.handle(msg)
|
|
141
148
|
} catch (e) {
|
|
142
149
|
if (isUnrecoverable(service, e)) e.unrecoverable = true
|
|
143
150
|
throw e
|
|
@@ -160,7 +167,6 @@ const processMessages = async (service, tenant, _opts = {}) => {
|
|
|
160
167
|
toBeDeleted,
|
|
161
168
|
toBeUpdated,
|
|
162
169
|
service,
|
|
163
|
-
emit: service._emitImmediate.bind(service),
|
|
164
170
|
options: opts
|
|
165
171
|
})
|
|
166
172
|
} catch (e) {
|
|
@@ -177,7 +183,7 @@ const processMessages = async (service, tenant, _opts = {}) => {
|
|
|
177
183
|
attempts: { '+=': 1 }
|
|
178
184
|
}
|
|
179
185
|
Object.assign(data, toBeUpdatedMsg)
|
|
180
|
-
if (data.lastError && typeof data.lastError !== 'string') data.lastError =
|
|
186
|
+
if (data.lastError && typeof data.lastError !== 'string') data.lastError = inspect(data.lastError)
|
|
181
187
|
queries.push(UPDATE(messagesEntity).where({ ID: toBeUpdatedMsg.ID }).set(data))
|
|
182
188
|
}
|
|
183
189
|
}
|
|
@@ -212,7 +218,7 @@ const processMessages = async (service, tenant, _opts = {}) => {
|
|
|
212
218
|
}
|
|
213
219
|
|
|
214
220
|
const registerMessageProcessor = (name, context) => {
|
|
215
|
-
const registry = context[messageProcessorRegistered] || (context[messageProcessorRegistered] = new Set())
|
|
221
|
+
const registry = context[$messageProcessorRegistered] || (context[$messageProcessorRegistered] = new Set())
|
|
216
222
|
if (!registry.has(name)) {
|
|
217
223
|
registry.add(name)
|
|
218
224
|
return true
|
|
@@ -221,7 +227,13 @@ const registerMessageProcessor = (name, context) => {
|
|
|
221
227
|
}
|
|
222
228
|
|
|
223
229
|
const _createMessage = (name, msg, context) => {
|
|
224
|
-
const _msg = {
|
|
230
|
+
const _msg = { [cdsUser]: context.user.id }
|
|
231
|
+
if (msg._fromSend || msg.reply) _msg._fromSend = true // send or emit?
|
|
232
|
+
if (msg.inbound) _msg.inbound = msg.inbound
|
|
233
|
+
if (msg.event) _msg.event = msg.event
|
|
234
|
+
if (msg.data) _msg.data = msg.data
|
|
235
|
+
if (msg.headers) _msg.headers = msg.headers
|
|
236
|
+
if (msg.query) _msg.query = msg.query
|
|
225
237
|
const outboxMsg = {
|
|
226
238
|
ID: cds.utils.uuid(),
|
|
227
239
|
target: name,
|
|
@@ -237,4 +249,62 @@ const writeInOutbox = async (name, msg, context) => {
|
|
|
237
249
|
return cds.tx(context).run(INSERT.into(messagesEntity).entries(outboxMsg))
|
|
238
250
|
}
|
|
239
251
|
|
|
240
|
-
|
|
252
|
+
// REVIST: Should we also support the following API?
|
|
253
|
+
// cds.outboxed(srv, {
|
|
254
|
+
// onInsert(msg){ ... }
|
|
255
|
+
// onForward(msg){ ... }
|
|
256
|
+
// onProcess(msgs){ ... }
|
|
257
|
+
// })
|
|
258
|
+
|
|
259
|
+
function outboxed(srv, customOpts) {
|
|
260
|
+
// outbox max. once
|
|
261
|
+
if (!new.target) {
|
|
262
|
+
const former = srv[$outboxed]
|
|
263
|
+
if (former) return former
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const originalSrv = srv.immediate || srv
|
|
267
|
+
const outboxedSrv = Object.create(originalSrv)
|
|
268
|
+
outboxedSrv.immediate = originalSrv
|
|
269
|
+
|
|
270
|
+
if (!new.target) Object.defineProperty(srv, $outboxed, { value: outboxedSrv })
|
|
271
|
+
|
|
272
|
+
const outboxOpts = Object.assign(
|
|
273
|
+
{},
|
|
274
|
+
(typeof cds.requires.outbox === 'object' && cds.requires.outbox) || {},
|
|
275
|
+
(typeof srv.options?.outbox === 'object' && srv.options.outbox) || {},
|
|
276
|
+
customOpts || {}
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
outboxedSrv.handle = async function (req) {
|
|
280
|
+
const context = req.context || cds.context
|
|
281
|
+
if (outboxOpts.kind === 'persistent-outbox' && hasPersistentOutbox(context.tenant)) {
|
|
282
|
+
// returns true if not yet registered
|
|
283
|
+
if (registerMessageProcessor(srv.name, context)) {
|
|
284
|
+
// NOTE: What if there are different outbox options for the same service?!
|
|
285
|
+
// There could be messages for srv1 with { maxAttempts: 1 }
|
|
286
|
+
// and messages for srv1 with { maxAttempts: 9 }.
|
|
287
|
+
// How would they be processed? I'd rather not have dedicated
|
|
288
|
+
// service names or store serialized options for each message.
|
|
289
|
+
context.on('succeeded', () => processMessages(originalSrv, context.tenant, outboxOpts))
|
|
290
|
+
}
|
|
291
|
+
await writeInOutbox(srv.name, req, context)
|
|
292
|
+
return
|
|
293
|
+
}
|
|
294
|
+
// REVISIT: Also allow maxAttempts for in-memory outbox?
|
|
295
|
+
context.on('succeeded', async () => {
|
|
296
|
+
try {
|
|
297
|
+
if (req.reply) await originalSrv.send(req)
|
|
298
|
+
else await originalSrv.emit(req)
|
|
299
|
+
} catch (e) {
|
|
300
|
+
LOG.error('Emit failed', { event: req.event, cause: e })
|
|
301
|
+
// opts.crashOnError is not official!!!
|
|
302
|
+
if (isUnrecoverable(originalSrv, e) && outboxOpts.crashOnError !== false) cds.exit(1)
|
|
303
|
+
}
|
|
304
|
+
})
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return outboxedSrv
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
module.exports = outboxed
|
|
@@ -3,7 +3,7 @@ const { INSERT, SELECT, UPDATE, DELETE } = cds.ql
|
|
|
3
3
|
|
|
4
4
|
const { where2obj } = require('../../_runtime/common/utils/cqn')
|
|
5
5
|
|
|
6
|
-
const { convertStructured } = require('../../common/utils/ucsn')
|
|
6
|
+
const { convertStructured } = require('../../_runtime/common/utils/ucsn')
|
|
7
7
|
const { deepCopy } = require('../../_runtime/common/utils/copy')
|
|
8
8
|
|
|
9
9
|
module.exports = (req, res, next) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sap/cds",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.4.0",
|
|
4
4
|
"description": "SAP Cloud Application Programming Model - CDS for Node.js",
|
|
5
5
|
"homepage": "https://cap.cloud.sap/",
|
|
6
6
|
"keywords": [
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@sap/cds-compiler": "^4",
|
|
37
37
|
"@sap/cds-fiori": "^1",
|
|
38
|
-
"@sap/cds-foss": "^
|
|
38
|
+
"@sap/cds-foss": "^5.0.0"
|
|
39
39
|
},
|
|
40
40
|
"cds": {
|
|
41
41
|
"plugins": [
|
package/apis/connect.d.ts
DELETED
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import { Service } from "./services"
|
|
2
|
-
|
|
3
|
-
export = cds
|
|
4
|
-
declare class cds {
|
|
5
|
-
|
|
6
|
-
connect : {
|
|
7
|
-
/**
|
|
8
|
-
* Connects to a specific datasource.
|
|
9
|
-
* @see [capire](https://cap.cloud.sap/docs/node.js/cds-connect#cds-connect-to)
|
|
10
|
-
*/
|
|
11
|
-
to (datasource: string, options?: ConnectOptions) : Promise<Service>
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Connects to a specific datasource via options.
|
|
15
|
-
* @see [capire](https://cap.cloud.sap/docs/node.js/cds-connect#cds-connect-to)
|
|
16
|
-
*/
|
|
17
|
-
to (options: ConnectOptions) : Promise<Service>
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Connects the primary datasource.
|
|
21
|
-
* @see [capire](https://cap.cloud.sap/docs/node.js/cds-connect)
|
|
22
|
-
*/
|
|
23
|
-
(options?: string | ConnectOptions) : Promise<typeof cds> //> cds.connect(<options>)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Emitted whenever a specific service is connected for the first time.
|
|
28
|
-
*/
|
|
29
|
-
on (event : 'connect', listener : (srv : Service) => void) : this
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
type ConnectOptions = {
|
|
34
|
-
impl?: string,
|
|
35
|
-
service?: string,
|
|
36
|
-
kind?:string,
|
|
37
|
-
model?:string,
|
|
38
|
-
credentials?: object
|
|
39
|
-
}
|
package/bin/utils/modules.js
DELETED
package/bin/utils/term.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
// FIXME: Nicht gut, das wir das zweimal redundant haben!
|
|
2
|
-
const debug = process.env.DEBUG
|
|
3
|
-
|
|
4
|
-
// https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences
|
|
5
|
-
const t = exports.codes = {
|
|
6
|
-
reset: '\x1b[0m', // Default
|
|
7
|
-
bold: '\x1b[1m', // Bold/Bright
|
|
8
|
-
link: '\x1b[4m', // underline
|
|
9
|
-
red: '\x1b[91m', // Bright Foreground Red
|
|
10
|
-
green: '\x1b[32m', // Foreground Green
|
|
11
|
-
orange: '\x1b[38;2;255;140;0m' // darker orange, works with bright and dark background
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
Object.defineProperty(exports, 'isTTY', { get: () => process.stdin.isTTY && process.stderr.isTTY })
|
|
15
|
-
|
|
16
|
-
const as = exports.as = (codes, o) => {
|
|
17
|
-
return exports.isTTY ? (codes + o + t.reset) : ('' + o)
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const asErr = exports.error = o => debug ? o : as(t.red + t.bold, o)
|
|
21
|
-
const asWarn = exports.warn = o => debug ? o : as(t.orange + t.bold, o)
|
|
22
|
-
const asInfo = exports.info = o => debug ? o : as(t.green + t.bold, o)
|
|
23
|
-
exports.warn = o => as(t.orange, o)
|
|
24
|
-
exports.info = o => as(t.green, o)
|
|
25
|
-
exports.link = o => as(t.link, o)
|
|
26
|
-
exports.bold = o => as(t.bold, o)
|
|
27
|
-
|
|
28
|
-
const format = exports.format = (o, severity='Error', asInternalError=false, withStack=false) => {
|
|
29
|
-
switch (severity) {
|
|
30
|
-
case 'Error' : return format.error (o, asInternalError, withStack)
|
|
31
|
-
case 'Warning': return format.warn (o)
|
|
32
|
-
default : return format.info (o)
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
// decorate.error, .warning, .info
|
|
37
|
-
// 'Error: foo' -> '[ERROR] foo' (Maven-like, allows for better grepping in logs)
|
|
38
|
-
Object.assign (format, {
|
|
39
|
-
error: (o, asInternalError, withStack) => {
|
|
40
|
-
if (debug) return o
|
|
41
|
-
if (asInternalError) {
|
|
42
|
-
return `[${asErr('INTERNAL ERROR')}] ${o.stack || o.toString()}\n`
|
|
43
|
-
}
|
|
44
|
-
return `[${asErr('ERROR')}] ${toString(o, 'Error', withStack)}`
|
|
45
|
-
},
|
|
46
|
-
warn: o => debug ? o : `[${asWarn('WARNING')}] ${toString(o, 'Warning')}`,
|
|
47
|
-
info: o => debug ? o : `[${asInfo('INFO')}] ${toString(o, 'Info')}`,
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
function toString(o, severity, withStack) {
|
|
51
|
-
if (!o || !o.toString) return o
|
|
52
|
-
return (withStack && o.stack ? o.stack : o.toString())
|
|
53
|
-
// strips the 'Error: ' prefix in the message, so that we can add our own prefix
|
|
54
|
-
.replace(new RegExp('^' + severity + ': ', 'i'), '') // beginning
|
|
55
|
-
.replace(new RegExp(' ' + severity + ':' , 'i'), '') // middle
|
|
56
|
-
}
|
package/lib/env/schema.js
DELETED
package/lib/linked/queries.js
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
const { entity } = require('./entities')
|
|
2
|
-
|
|
3
|
-
/** Lazily resolves a query's _target property */
|
|
4
|
-
module.exports = (q,defs) => {
|
|
5
|
-
if (!q._target || q._target.kind !== 'entity') Object.defineProperty (q, '_target', {value:(
|
|
6
|
-
q.SELECT ? _resolve (q.SELECT.from, defs) :
|
|
7
|
-
q.INSERT ? _resolve (q.INSERT.into, defs) :
|
|
8
|
-
q.UPSERT ? _resolve (q.UPSERT.into, defs) :
|
|
9
|
-
q.UPDATE ? _resolve (q.UPDATE.entity, defs) :
|
|
10
|
-
q.DELETE ? _resolve (q.DELETE.from, defs) :
|
|
11
|
-
q.STREAM?.from ? _resolve (q.STREAM.from, defs) :
|
|
12
|
-
q.STREAM?.into ? _resolve (q.STREAM.into, defs) :
|
|
13
|
-
_resolve (undefined)
|
|
14
|
-
), configurable:true, writable:true })
|
|
15
|
-
return q._target
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const _resolve = (from, defs) => {
|
|
19
|
-
if (!from || from.name) return from
|
|
20
|
-
while (from.SELECT) from = from.SELECT.from
|
|
21
|
-
if (from.join || from.set) return //_unresolved()
|
|
22
|
-
if (from.ref) {
|
|
23
|
-
if (from.ref.length === 1) {
|
|
24
|
-
from = from.ref[0]
|
|
25
|
-
if (from.id) from = from.id
|
|
26
|
-
} else {
|
|
27
|
-
let target = {elements:defs}
|
|
28
|
-
for (let each of from.ref) {
|
|
29
|
-
const e = each.id || each
|
|
30
|
-
const a = target.elements[e]; if (!a) return _unresolved (target.name +':'+e)
|
|
31
|
-
target = defs [a.target || a.name]; if (!target) return _unresolved (a.target)
|
|
32
|
-
}
|
|
33
|
-
return target
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return defs[from] || _unresolved(from)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const _unresolved = (name) => {
|
|
40
|
-
return { name, __proto__:entity.prototype, _unresolved:true }
|
|
41
|
-
}
|