{"id":41481674,"url":"https://github.com/capire/xflights","last_synced_at":"2026-01-23T17:21:05.993Z","repository":{"id":312109733,"uuid":"1006476807","full_name":"capire/xflights","owner":"capire","description":"Master data service for flights, airlines, airports ","archived":false,"fork":false,"pushed_at":"2026-01-18T13:26:31.000Z","size":122,"stargazers_count":5,"open_issues_count":5,"forks_count":2,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-18T20:28:25.952Z","etag":null,"topics":["cap","cds","fligths","reuse"],"latest_commit_sha":null,"homepage":"","language":"CAP CDS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/capire.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-06-22T11:09:40.000Z","updated_at":"2026-01-18T13:26:35.000Z","dependencies_parsed_at":"2025-08-28T22:19:33.473Z","dependency_job_id":"4da576e9-442b-4229-985c-bcace10b6369","html_url":"https://github.com/capire/xflights","commit_stats":null,"previous_names":["capire/xflights"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/capire/xflights","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capire%2Fxflights","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capire%2Fxflights/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capire%2Fxflights/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capire%2Fxflights/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/capire","download_url":"https://codeload.github.com/capire/xflights/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capire%2Fxflights/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28696523,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-23T15:57:05.722Z","status":"ssl_error","status_checked_at":"2026-01-23T15:56:27.656Z","response_time":59,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cap","cds","fligths","reuse"],"created_at":"2026-01-23T17:21:05.129Z","updated_at":"2026-01-23T17:21:05.986Z","avatar_url":"https://github.com/capire.png","language":"CAP CDS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @capire/xflights\n\nThis is a reuse package to manage and serve master data like _Airlines_, _Airports_, and _Flights_.\nIt publishes a [pre-built client package](#publishing-apis), that is used in the [xtravels](https://github.com/capire/xtravels) application.\n\n##### Table of Contents\n\n- [Domain Model](#domain-model)\n- [Service Interfaces](#service-interfaces)\n- [Exporting APIs](#exporting-apis)\n- [Publishing APIs](#publishing-apis)\n- [Consuming APIs](#consuming-apis)\n- [Using Workspaces](#using-workspaces)\n\n\n\n\n## Domain Model\n\nThe domain model is defined in [_db/schema.cds_](./db/schema.cds). It centers around normalized `FlightConnections`, which connect two `Airports` operated by an `Airline`, while entity `Flights` represents scheduled flights on specific dates with a specific aircraft and price.\n\n![](_docs/domain-model.drawio.svg)\n\n\n## Service Interfaces\n\nTwo service interfaces are defined in [_srv/admin-service.cds_](./srv/admin-service.cds), and [_srv/data-service.cds_](./srv/data-service.cds), to serve different use cases as shown below: \n\n- an admin service to _maintain_ the master data from UIs or remote systems\n- a data service to _consume_ it from remote applications\n\n![](_docs/services.drawio.svg)\n\n\n\u003e [!tip] \n\u003e\n\u003e \u003cdetails\u003e \u003csummary\u003e Serving denormalized views \u003c/summary\u003e\n\u003e The data service exposes a denormalized view of `Flights` and associated `FlightConnections` data, essentially declared like that: \n\u003e\n\u003e ```cds\n\u003e entity Flights as projection on my.Flights { \n\u003e   *,          // all elements from Flights\n\u003e   flight.*,   // all elements from FlightConnections\n\u003e }\n\u003e ```\n\u003e \n\u003e With that consumers aren't bothered with normalized data but can just consume flat data, looking like that:\n\u003e\n\u003e ![](_docs/data-service.drawio.svg)\n\u003e\n\u003e \u003c/details\u003e\n\n\n\n## Exporting APIs\n\nGiven the respective service definition, we create a pre-built client package for the data API, which can be used from consuming apps in a plug-and-play fashion.\n\n![](_docs/client-packages.drawio.svg)\n\nWe use `cds export` to create the API package, based on the Data Service definition:\n\n```sh\ncds export srv/data-service.cds\n```\n\nThis generates a separate CAP reuse package within subfolder [_apis/data-service_](./apis/data-service/) that contains only the effective service API definitions, accompanied by automatically derived test data and i18n bundles. \n\n![](_docs/data-service-api.drawio.svg)\n\nInitially, `cds export` also adds a `package.json`, which we can modify as appropriate, and did so by changing the package name to `@capire/xflights-data`:\n\n```diff\n{\n- \"name\": \"@capire/xflights-data-service\",\n+ \"name\": \"@capire/xflights-data\",\n  ...\n}\n```\n\n\n\n## Publishing APIs\n\nWe can finally share this package with consuming applications using standard ways, like `npm publish`:\n\n```sh\ncd apis/data-service\nnpm publish\n```\n\n\n\u003e [!tip]\n\u003e\n\u003e \u003cdetails\u003e \u003csummary\u003eUsing GitHub Packages\u003c/summary\u003e\n\u003e\n\u003e Within the [_capire_](https://github.com/capire) org, we're publishing to [GitHub Packages](https://docs.github.com/packages), which requires you to npm login once like that:\n\u003e\n\u003e ```sh\n\u003e npm login --scope=@capire --registry=https://npm.pkg.github.com\n\u003e ```\n\u003e\n\u003e As password you're using a Personal Access Token (classic) with `read:packages` scope (for retrieving and installing a package). Read more about that in [Authenticating to GitHub Packages](https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-npm-registry#authenticating-to-github-packages).\n\u003e \u003c/details\u003e\n\n\n\n## Consuming APIs\n\nUse the published client package in your consuming application by installing it via `npm`:\n\n```sh\nnpm add @capire/xflights-data\n```\n\nWith that, we can use the imported models as usual, and as if they were local in mashups with our own entities like so:\n\n```cds\nusing { sap.capire.flights.data as imported } from '@capire/xflights-data';\nentity TravelBookings { //...\n  flight : Association to imported.Flights;\n}\n```\n\n▷ Learn more about consuming APIs and CAP-level data integration in the [_xtravels_ application](https://github.com/capire/xtravels/blob/main/db/xflights.cds).\n\n\n\n## Using Workspaces\n\nInstead of exercising a workflow like that again and again:\n\n- ( *develop* → *export* → *publish* ) → *npmjs.com* → ( *update* → *consume* )\n\n... we can use *npm workspaces* technique to work locally and speed up things as follows:\n\n```shell \nmkdir -p cap/works; cd cap/works\ngit clone https://github.com/capire/xflights\ngit clone https://github.com/capire/xtravels\necho '{\"workspaces\":[\"xflights\",\"xtravels\"]}' \u003e package.json\n```\n\nAdd a link to the local `@capire/xflights-data` API package, enclosed with the cloned xflights sources:\n\n```shell\nnpm add ./xflights/apis/data-service\n```\n\nCheck the installation using `npm ls`, which would yield output as below, showing that `@capire/xtravel`'s dependency to `@capire/xflights-data` is nicely fulfilled by a local link to `./xflights/apis/data-service`:\n\n```shell\nnpm ls @capire/xflights-data\n```\n\n```zsh\nworks@ ~/cap/works\n├── @capire/xflights-data@0.1.11 -\u003e ./xflights/apis/data-service\n└─┬ @capire/xtravels@1.0.0 -\u003e ./xtravels\n  └── @capire/xflights-data@0.1.11 deduped -\u003e ./xflights/apis/data-service\n```\n\nStart the xtravels application → and note the sources loaded from *./xflights/apis/data-service*, and the information further below about the `sap.capire.flights.data` service mocked automatically:\n\n```shell\ncds watch xtravels\n```\n\n```zsh\n[cds] - loaded model from 20 file(s):\n\n  xtravels/srv/travel-service.cds\n  xtravels/db/schema.cds\n  xtravels/db/xflights.cds\n  xflights/apis/data-service/index.cds\n  xflights/apis/data-service/services.csn\n  ...\n```\n\n```zsh\n[cds] - mocking sap.capire.flights.data {\n  at: [ '/odata/v4/data', '/rest/data', '/hcql/data' ],\n  decl: 'xflights/apis/data-service/services.csn:3',\n}\n```\n\n\n\n## Using Proxy Packages\n\nThe usage of *npm workspaces* technique as described above streamlined our workflows as follows:\n\n- Before: ( *develop* → *export* → *publish* ) → *npmjs.com* → ( *update* → *consume* )\n- After: ( *develop* → *export* ) → ( *consume* )\n\nWe can even more streamline that by eliminating the export step as follows...\n\nCreate a new subfolder `xflights-api-shortcut`  in which we add two files as follows:\n\n```shell\nmkdir xflights-api-shortcut\n```\n\nAdd a `package.json` file in there with that content:\n\n```json\n{\n  \"name\": \"@capire/xflights-data\",\n  \"dependencies\": {\n    \"@capire/xflights\": \"*\"\n  }\n}\n```\n\nAnd an `index.cds` file with that content:\n\n```cds\nusing from '@capire/xflights/srv/data-service';\n```\n\n\u003cdetails\u003e \u003csummary\u003e Using the shell's \"here document\" technique \u003c/summary\u003e\n\n  You can also create those two files from the command line as follows:\n  ```shell\n  cat \u003e xflights-api-shortcut/package.json \u003c\u003c EOF\n  {\n    \"name\": \"@capire/xflights-data\",\n    \"dependencies\": {\n      \"@capire/xflights\": \"*\"\n    }\n  }\n  EOF\n  ```\n  \n  Take the same approach for the `index.cds` file:\n  ```shell\n  cat \u003e xflights-api-shortcut/index.cds \u003c\u003c EOF\n  using from '@capire/xflights/srv/data-service';\n  EOF\n  ```\n\n\u003c/details\u003e\nWith that in place, change our API package dependency in the workspace root as follows:\n\n```shell\nnpm add ./xflights-api-shortcut\n```\n\nCheck the effect of that → note how `@capire/xflights-data` dependencies now link to `./xflights-api-shortcut`:\n\n```shell\nnpm ls @capire/xflights-data\n```\n\n```zsh\nworks@ ~/cap/works\n├── @capire/xflights-data@ -\u003e ./xflights-api-shortcut\n└─┬ @capire/xtravels@1.0.0 -\u003e ./xtravels\n  └── @capire/xflights-data@ deduped -\u003e ./xflights-api-shortcut≤\n```\n\nStart the *xtravels* application → and note the sources loaded from *./xflights-api-shortcut*, and the information further below about the `sap.capire.flights.data` service now being _served_, not _mocked_ anymore:\n\n```shell\ncds watch xtravels\n```\n\n```zsh\n[cds] - loaded model from 20 file(s):\n\n  xtravels/srv/travel-service.cds\n  xtravels/db/schema.cds\n  xtravels/db/xflights.cds\n  xflights-api-shortcut/index.cds\n  xflights/srv/data-service.cds\n  xflights/db/schema.cds  \n  ...\n```\n\n```zsh\n[cds] - serving sap.capire.flights.data {\n  at: [ '/odata/v4/data', '/rest/data', '/hcql/data' ],\n  decl: 'xflights/apis/data-service/services.csn:3',\n}\n```\n\nWhich means we've streamlined our workflows as follows:\n\n- Before: ( *change* → *export* → *publish* ) → *npmjs.com* → ( *update* → *consume* )\n- Step 1: ( *change* → *export* ) → ( *consume* )\n- Step 2: ( *change* ) → ( *consume* )\n\n\n\n## License\n\nCopyright (c) 2026 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, version 2.0 except as noted otherwise in the [LICENSE](LICENSE) file.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapire%2Fxflights","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcapire%2Fxflights","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapire%2Fxflights/lists"}