Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: event resources generation #55

Merged
merged 11 commits into from
Sep 12, 2024
Merged

fix: event resources generation #55

merged 11 commits into from
Sep 12, 2024

Conversation

ductaily
Copy link
Contributor

@ductaily ductaily commented Sep 2, 2024

Address issues from #38

eventResources

  • The entries are service-level, not event-level
  • IMPORTANT: test with more than one event declared per service → should end up in one entry, not many

@ductaily
Copy link
Contributor Author

ductaily commented Sep 2, 2024

I extended service definitions of bookshop in the test:

using { sap.capire.bookshop as my } from '../db/schema';
service AdminService @(requires:'authenticated-user') { 
  entity Books as projection on my.Books;
  entity Authors as projection on my.Authors;

  event BookCreated : {
    ID    : Integer;
    title : String @title: 'Title';
  };

  event BookDeleted : {
    ID    : Integer;
  };

  event BookUpdated : {
    ID    : Integer;
    title : String @title: 'Title';
  }
}
using { sap.capire.bookshop as my } from '../db/schema';
service CatalogService @(path:'/browse') { 

  @readonly entity Books as select from my.Books {*,
    author.name as author
  } excluding { createdBy, modifiedBy };

  @requires: 'authenticated-user'
  action submitOrder (book: Books:ID, quantity: Integer);
  
  event BookCreated : {
      ID    : Integer;
    title : String @title: 'Title';
  };

  event BookDeleted : {
    ID    : Integer;
  };

  event BookUpdated : {
    ID    : Integer;
    title : String @title: 'Title';
  }
}

Resulting ORD Document:

{
  "$schema": "https://sap.github.io/open-resource-discovery/spec-v1/interfaces/Document.schema.json",
  "apiResources": [
     //...
  ],
  "description": "this is an application description",
  "eventResources": [
    {
      "description": "This is an example event catalog that contains only a partial ODM cap-js-ord V1 event",
      "extensible": {
        "supported": "no",
      },
      "ordId": "capjs.ord:eventResource:undefined.AdminService:v1",
      "partOfGroups": [
        "sap.cds:service:capjs.ord:undefined.AdminService",
      ],
      "partOfPackage": "capjsord:package:undefined:v1",
      "releaseStatus": "beta",
      "resourceDefinitions": [
        {
          "accessStrategies": [
            {
              "type": "open",
            },
          ],
          "mediaType": "application/json",
          "type": "asyncapi-v2",
          "url": "/.well-known/open-resource-discovery/v1/api-metadata/AdminService.asyncapi2.json",
        },
      ],
      "shortDescription": "Example ODM Event",
      "title": "ODM capjsord Events",
      "version": "1.0.0",
      "visibility": "public",
    },
    {
      "description": "This is an example event catalog that contains only a partial ODM cap-js-ord V1 event",
      "extensible": {
        "supported": "no",
      },
      "ordId": "capjs.ord:eventResource:undefined.CatalogService:v1",
      "partOfGroups": [
        "sap.cds:service:capjs.ord:undefined.CatalogService",
      ],
      "partOfPackage": "capjsord:package:undefined:v1",
      "releaseStatus": "beta",
      "resourceDefinitions": [
        {
          "accessStrategies": [
            {
              "type": "open",
            },
          ],
          "mediaType": "application/json",
          "type": "asyncapi-v2",
          "url": "/.well-known/open-resource-discovery/v1/api-metadata/CatalogService.asyncapi2.json",
        },
      ],
      "shortDescription": "Example ODM Event",
      "title": "ODM capjsord Events",
      "version": "1.0.0",
      "visibility": "public",
    },
  ],
  "groups": [
    {
      "groupId": "sap.cds:service:capjs.ord:undefined.AdminService",
      "groupTypeId": "sap.cds:service",
      "title": "Admin Service Title",
    },
    {
      "groupId": "sap.cds:service:capjs.ord:undefined.CatalogService",
      "groupTypeId": "sap.cds:service",
      "title": "Catalog Service Title",
    },
  ],
  "openResourceDiscovery": "1.9",
  "packages": [
    {
      "description": "Description for capjs ord",
      "ordId": "capjsord:package:undefined:v1",
      "partOfProducts": [
        "customer:product:capjs.ord:",
      ],
      "shortDescription": "Short description for capjs ord",
      "title": "capjs ord",
      "vendor": "customer:vendor:Customer:",
      "version": "1.0.0",
    },
  ],
  "policyLevel": "none",
  "products": [
    {
      "ordId": "customer:product:cap.js.ord:",
      "shortDescription": "Description for cap js ord",
      "title": "cap js ord",
      "vendor": "customer:vendor:customer:",
    },
  ],
}

@Fannon

@ductaily ductaily marked this pull request as ready for review September 2, 2024 15:38
@ductaily
Copy link
Contributor Author

ductaily commented Sep 2, 2024

Result with our example:
document.json

lib/ord.js Outdated Show resolved Hide resolved
Co-authored-by: Zongqi Chen <137198879+zongqichen@users.noreply.github.com>
@@ -113,14 +112,9 @@ const fGetGroups = (csn, global) => {
// storing the group ids in a set to avoid duplicates
let groupIds = new Set();

let serviceGroups = global.aServices
return global.aServices
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know it's not your problem, but this function implementation is really wired:

  1. We should avoid using global to store data.
  2. If we have to use global, we should not pass it as argument, which against the usage of global.
  3. The name 'global.aServices' is really confused. I would suggest that, later we use oop to refactor it.
  4. The function name and return are also confused. The name is fGetGroups, and I would expect to get the list of group. But the return value is indirectly indication. I would suggest, either we define a variable: 'const groupList' and return this variable, or remove line "let groupIds = new Set();", e.g
const fGetGroups = (csn, global) => return global.aServices
 .map((serviceName) => fCreateGroupsTemplateForService(serviceName, csn.definitions[serviceName], new Set()))
 .filter((resource) => resource !== null && resource !== undefined);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few cents from my side:

  1. We should avoid using global to store data.
  2. If we have to use global, we should not pass it as argument, which against the usage of global.

This probably just my preference. I don't really want to mock a global variable in tests and rather pass a mocked object into the function. Not sure what the others think about it.

  1. The name 'global.aServices' is really confused. I would suggest that, later we use oop to refactor it.

Could you please elaborate what exactly is confusing you?

The whole project uses a functional programming approach. Not sure how much sense it makes to switch to a totally different concept.

  1. The function name and return are also confused. The name is fGetGroups, and I would expect to get the list of group. But the return value is indirectly indication. I would suggest, either we define a variable: 'const groupList' and return this variable, or remove line "let groupIds = new Set();", e.g ...

Good point. It would even make sense to remove the groupIds from the function signature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thx @ductaily, I see https://github.com/cap-js/ord/blob/main/lib/ord.js#L163, the global is the name of object. This is what I want, but the name is conflict with javascript keyword. We should avoid it. And good point, the naming pattern for example aServices and fGetGroups, we should have agreement in discussion.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to document something that @zongqichen and I discussed via call:

I don't think that global is a global variable. It's very likely a variable that the CAP Framework passes into the plugins, to pass a global context, where the CAP framework keeps the overall information on what is part of the current application. This is where you find a list of all services, entities etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was also my understanding what the global variable here is. I misinterpreted the statements above.

lib/ord.js Outdated Show resolved Hide resolved
Comment on lines +40 to +41
let service = match.groups?.service
if (service.startsWith("undefined")) service = service.replace("undefined.", "")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you explain these two lines? And service seems to imply to serviceName?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, service imply serviceName, you can see it in the group id regex as a named capturing group.

The implementation here is not finished but my goal was to find the corresponding service in the CSN definition using the information I have in the ORD Document. In this case, I want to find that the eventResource partOfGroups is assigned to a groupId that is actually a service in the CSN.

Since they are attaching the namespace in the groupId, I want to remove the namespace part here to find the corresponding CSN definition. In this case, undefined.

I will improve this to check for the namespace and remove the namespace instead of undefined.

I hope this answered the question.

ductaily and others added 3 commits September 3, 2024 14:17
Co-authored-by: Zongqi Chen <137198879+zongqichen@users.noreply.github.com>
@ductaily
Copy link
Contributor Author

ductaily commented Sep 3, 2024

The tests are failing and I can't reproduce the error on @zongqichen and my machine.

@RoshniNaveenaS Do you have an idea what could be the cause and how we could resolve it?

@ductaily
Copy link
Contributor Author

ductaily commented Sep 4, 2024

The tests are failing and I can't reproduce the error on @zongqichen and my machine.

@RoshniNaveenaS Do you have an idea what could be the cause and how we could resolve it?

I see now that the failure is caused by the new CDS Version: https://github.tools.sap/cap/cds/releases/tag/rel%2F8.2.0
The LinkedDefinitions were changed and do not contain map, forEach, ... anymore.

@zongqichen
Copy link
Contributor

The tests are failing and I can't reproduce the error on @zongqichen and my machine.
@RoshniNaveenaS Do you have an idea what could be the cause and how we could resolve it?

I see now that the failure is caused by the new CDS Version: https://github.tools.sap/cap/cds/releases/tag/rel%2F8.2.0 The LinkedDefinitions were changed and do not contain map, forEach, ... anymore.

Cool, your commit has fixed it. I have one more question, it seems github action will always install the latest version of cds, and brings the issue like it. We should control peerDepdencies upper limits as well?

lib/templates.js Outdated
@@ -289,7 +289,7 @@ const fCreateEventResourceTemplate = (srv, srvDefinition, global,packageIds) =>
*/
function checkEntityFunctionAction(srvDefinition, global) {
if (srvDefinition.entities) {
return srvDefinition.entities.map((entity) => {
return [...srvDefinition.entities].map((entity) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there are 5 more places need to be adjust, for example srvDefinition.actions.map. But we don't have corresponding test, lets ignore it in this pr.



describe("eventResources", () => {
const GROUP_ID_REGEX = /^([a-z0-9-]+(?:[.][a-z0-9-]+)*):([a-zA-Z0-9._\-/]+):([a-z0-9-]+(?:[.][a-z0-9-]+)*):(?<service>[a-zA-Z0-9._\-/]+)$/
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this idea to have named groups in a regexp!

@ductaily
Copy link
Contributor Author

ductaily commented Sep 9, 2024

The tests are failing and I can't reproduce the error on @zongqichen and my machine.
@RoshniNaveenaS Do you have an idea what could be the cause and how we could resolve it?

I see now that the failure is caused by the new CDS Version: https://github.tools.sap/cap/cds/releases/tag/rel%2F8.2.0 The LinkedDefinitions were changed and do not contain map, forEach, ... anymore.

Cool, your commit has fixed it. I have one more question, it seems github action will always install the latest version of cds, and brings the issue like it. We should control peerDepdencies upper limits as well?

@zongqichen Yes, we should specify the exact version.

@ductaily ductaily requested a review from Fannon September 9, 2024 08:20
"extensible": {
"supported": "no",
},
"ordId": "capjs.ord:eventResource:undefined.AdminService:v1",
Copy link
Contributor

@Fannon Fannon Sep 9, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still feel bad about all those undefined here. But this is planned to be fixed with a follow up PR?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I will fix it in next PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The undefined issues are all related and coming from the global.capNamespace. That will also fix this.

@aramovic79
Copy link
Contributor

@ductaily: There are a few merge conflicts to be resolved...

@zongqichen @Fannon

@ductaily
Copy link
Contributor Author

ductaily commented Sep 9, 2024

@ductaily: There are a few merge conflicts to be resolved...

@zongqichen @Fannon

Done.

@aramovic79
Copy link
Contributor

@RoshniNaveenaS @RamIndia : Can we merge this PR?
cc: @ductaily @zongqichen @Fannon

@aramovic79
Copy link
Contributor

@ductaily : I guess the following one is solved as well, correct?
The groups for events shall be services, not the individual events → but then the last two entries in the bookstore sample are duplicate

@ductaily
Copy link
Contributor Author

@ductaily : I guess the following one is solved as well, correct? The groups for events shall be services, not the individual events → but then the last two entries in the bookstore sample are duplicate

Correct. This PR would also solve that issue.

Copy link
Contributor

@RamIndia RamIndia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Checked the generated documents for incidents app, looks fine as well

@aramovic79 aramovic79 merged commit e9d6538 into main Sep 12, 2024
3 checks passed
@aramovic79 aramovic79 deleted the fix/event-resources branch September 12, 2024 08:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants