Skip to content

Commit a5ed53d

Browse files
authored
chore: revert manual path calculation (#15)
* revert manual path * . * .
1 parent 4fd06aa commit a5ed53d

File tree

2 files changed

+39
-102
lines changed

2 files changed

+39
-102
lines changed

lib/setModel.js

Lines changed: 37 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,45 @@ async function compileModel(path) {
3131
if (!compiled.definitions || Object.keys(compiled.definitions).length === 0) {
3232
throw new Error(`Compiled CDS model is invalid or empty for path: ${path}`)
3333
}
34-
try {
35-
compiled = cds.compile.for.odata(compiled) // needed for drafts
36-
} catch {
37-
// nothing to do
34+
compiled = cds.compile.for.odata(compiled) // to include drafts
35+
const serviceInfo = cds.compile.to.serviceinfo(compiled)
36+
37+
// merge with definitions
38+
for (const info of serviceInfo) {
39+
const def = compiled.definitions[info.name]
40+
Object.assign(def, info)
41+
}
42+
43+
const _entities_in = service => {
44+
const exposed = [],
45+
{ entities } = service
46+
for (let each in entities) {
47+
const e = entities[each]
48+
if (e['@cds.autoexposed'] && !e['@cds.autoexpose']) continue
49+
if (/DraftAdministrativeData$/.test(e.name)) continue
50+
if (/[._]texts$/.test(e.name)) continue
51+
if (cds.env.effective.odata.containment && service.definition._containedEntities.has(e.name)) continue
52+
exposed.push(each)
53+
}
54+
return exposed
3855
}
3956

40-
augmentModel(compiled)
57+
compiled.services
58+
.flatMap(srv => srv.endpoints.map(endpoint => ({ srv, endpoint })))
59+
.map(({ srv, endpoint }) => {
60+
const entities = _entities_in(srv)
61+
for (const e of entities) {
62+
const path = endpoint.path + e.replace(/\./g, '_')
63+
const def = compiled.definitions[srv.name + '.' + e]
64+
def.endpoints ??= []
65+
def.endpoints.push({ kind: endpoint.kind, path })
66+
// Add fully qualified entity names to each service as 'exposedEntities'
67+
}
68+
})
69+
70+
for (const service of compiled.services) {
71+
service.exposedEntities = _entities_in(service, compiled)
72+
}
4173

4274
const endTime = Date.now()
4375
const compileDuration = endTime - startTime
@@ -68,101 +100,6 @@ async function refreshModel(path) {
68100
}
69101
}
70102

71-
// --- Helper functions below ---
72-
73-
// Augments the compiled CDS model with endpoints and exposed entities
74-
function augmentModel(compiled) {
75-
for (const defName in compiled.definitions) {
76-
// Add name for each definition
77-
const def = compiled.definitions[defName]
78-
def.name = defName
79-
}
80-
81-
const _entities_in = (srv, compiled) => {
82-
const exposed = []
83-
const entities = Object.keys(compiled.definitions).filter(name => name.startsWith(srv.name + '.'))
84-
for (let each of entities) {
85-
const e = compiled.definitions[each]
86-
if (e['@cds.autoexposed'] && !e['@cds.autoexpose']) continue
87-
if (/DraftAdministrativeData$/.test(e.name)) continue
88-
if (/[._]texts$/.test(e.name)) continue
89-
// ignore for now
90-
// if (cds.env.effective.odata.containment && service.definition._containedEntities.has(e.name)) continue
91-
exposed.push(each)
92-
}
93-
return exposed
94-
}
95-
96-
// construct endpoint for each entity and add it to its definition
97-
Object.keys(compiled.definitions)
98-
.filter(name => compiled.definitions[name].kind === 'service')
99-
.map(name => {
100-
const srv = compiled.definitions[name]
101-
srv.endpoints = getEndpoints(srv)
102-
return srv
103-
})
104-
.flatMap(srv => srv.endpoints.map(endpoint => ({ srv, endpoint })))
105-
.map(({ srv, endpoint }) => {
106-
const entities = _entities_in(srv, compiled)
107-
srv.exposedEntities = []
108-
for (const e of entities) {
109-
const eRelName = e.slice(srv.name.length + 1)
110-
srv.exposedEntities.push(eRelName)
111-
const path = endpoint.path + eRelName.replace(/\./g, '_')
112-
const def = compiled.definitions[e]
113-
def.endpoints ??= []
114-
def.endpoints.push({ kind: endpoint.kind, path })
115-
}
116-
})
117-
}
118-
119-
// Partially taken over from @sap/cds, to avoid `compile.for.nodejs` and `compile.to.serviceinfo`
120-
// or starting the real application.
121-
// Custom servers (with paths defined in code) are not supported.
122-
// TODO: Check how it works in Java.
123-
const getEndpoints = srv => {
124-
const _slugified = name =>
125-
/[^.]+$/
126-
.exec(name)[0] //> my.very.CatalogService --> CatalogService
127-
.replace(/Service$/, '') //> CatalogService --> Catalog
128-
.replace(/_/g, '-') //> foo_bar_baz --> foo-bar-baz
129-
.replace(/([a-z0-9])([A-Z])/g, (_, c, C) => c + '-' + C) //> ODataFooBarX9 --> OData-Foo-Bar-X9
130-
.toLowerCase() //> FOO --> foo
131-
let annos = srv['@protocol']
132-
if (annos) {
133-
if (annos === 'none' || annos['='] === 'none') return []
134-
if (!annos.reduce) annos = [annos]
135-
} else {
136-
annos = []
137-
for (const kind of ['odata', 'rest']) {
138-
let path = srv['@' + kind] || srv['@protocol.' + kind]
139-
if (path) annos.push({ kind, path })
140-
}
141-
}
142-
143-
if (!annos.length) annos.push({ kind: 'odata' })
144-
145-
const endpoints = annos.map(each => {
146-
let { kind = each['='] || each, path } = each
147-
if (typeof path !== 'string') path = srv['@path'] || _slugified(srv.name)
148-
if (path[0] !== '/')
149-
path =
150-
{
151-
'odata-v4': '/odata/v4',
152-
odata: '/odata/v4',
153-
'odata-v2': '/odata/v2',
154-
rest: '/rest',
155-
hcql: '/hcql'
156-
}[kind] +
157-
'/' +
158-
path // prefix with protocol path
159-
if (!path.endsWith('/')) path = path + '/'
160-
return { kind, path }
161-
})
162-
163-
return endpoints
164-
}
165-
166103
// Global cache object for CDS file timestamps
167104
const cache = { cdsFiles: new Map() }
168105
let changeWatcher = null

tests/tools.test.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ test.describe('tools', () => {
2020
assert(Array.isArray(result[0].endpoints), 'Should contain endpoints')
2121
assert.equal(result[0].name, 'AdminService', 'Should find Adminservice.Books service')
2222
assert.equal(result[0].endpoints[0].kind, 'odata', 'Should contain odata endpoint kind')
23-
assert.equal(result[0].endpoints[0].path, '/odata/v4/admin/', 'Should contain endpoint path')
23+
assert.equal(result[0].endpoints[0].path, 'odata/v4/admin/', 'Should contain endpoint path')
2424
})
2525

2626
test('search_cds_definitions: fuzzy search for Books entity', async () => {
@@ -35,7 +35,7 @@ test.describe('tools', () => {
3535
assert(books[0].name, 'AdminService.Books', 'Should find AdminService.Books entity')
3636
assert(Array.isArray(books[0].endpoints), 'Should contain endpoints')
3737
assert.equal(books[0].endpoints[0].kind, 'odata', 'Should contain odata endpoint kind')
38-
assert.equal(books[0].endpoints[0].path, '/odata/v4/admin/Books', 'Should contain endpoint path')
38+
assert.equal(books[0].endpoints[0].path, 'odata/v4/admin/Books', 'Should contain endpoint path')
3939
})
4040

4141
test('list_all_cds_definition_names: should list all entities', async () => {

0 commit comments

Comments
 (0)