diff --git a/packages/api-client/README.md b/packages/api-client/README.md index 253499edd..84dfcdafd 100644 --- a/packages/api-client/README.md +++ b/packages/api-client/README.md @@ -39,24 +39,6 @@ client.on('door_states', console.log); Requirements: * java >= 8 - -Download the swagger codegen -```bash -wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.25/swagger-codegen-cli-3.0.25.jar -O .bin/swagger-codegen-cli.jar -``` - -Run the api-server locally -```bash -cd ../api_server -npm start -``` - -Generate code -```bash -java -jar .bin/swagger-codegen-cli.jar generate -ihttp://localhost:8000/openapi.json -ltypescript-axios -olib/openapi -``` - -There is a bug with `ModelObject` type being missing, workaround it by adding a type to the generated models. ```bash -echo 'export type ModelObject = Record;' >> lib/openapi/models/index.ts +./generate-openapi.sh ``` diff --git a/packages/api-client/generate-openapi.py b/packages/api-client/generate-openapi.py new file mode 100644 index 000000000..bca133710 --- /dev/null +++ b/packages/api-client/generate-openapi.py @@ -0,0 +1,9 @@ +import json +import os + +from api_server.app import app + +here = os.path.realpath(os.path.dirname(__file__)) +os.makedirs(f"{here}/build", exist_ok=True) +with open(f"{here}/build/openapi.json", "w") as f: + json.dump(app.openapi(), f) diff --git a/packages/api-client/generate-openapi.sh b/packages/api-client/generate-openapi.sh new file mode 100755 index 000000000..8d78211d6 --- /dev/null +++ b/packages/api-client/generate-openapi.sh @@ -0,0 +1,44 @@ +#!/bin/bash +set -e + +function usage() { + echo "Usage: generate-models.sh" +} + +cd $(dirname $0) + +source ../../scripts/version.sh + +expected_sha='cde6255246cf76b9e4c20e85968d36505930700f8adad68e76c0bc5a6721bfe5' + +if [[ ! -f '.bin/swagger-codegen-cli.jar' ]]; then + wget https://repo1.maven.org/maven2/io/swagger/codegen/v3/swagger-codegen-cli/3.0.25/swagger-codegen-cli-3.0.25.jar -O .bin/swagger-codegen-cli.jar +fi + +sha=$(sha256sum .bin/swagger-codegen-cli.jar | awk '{print $1}') + +if [[ $sha != $expected_sha ]]; then + echo "ERR: .bin/swagger-codegen-cli.jar sha doesn't match" + exit 1 +fi + +swagger_ver=$(java -jar .bin/swagger-codegen-cli.jar version) +java -jar .bin/swagger-codegen-cli.jar generate -i'build/openapi.json' -ltypescript-axios -olib/openapi +# There is a bug with `ModelObject` type being missing, workaround it by adding a type to the generated models. +echo 'export type ModelObject = Record;' >> lib/openapi/models/index.ts + +rmf_server_ver=$(getVersion .) + +cat << EOF > lib/version.ts +// THIS FILE IS GENERATED +import { version as rmfModelVer } from 'rmf-models'; + +export const version = { + rmfModels: rmfModelVer, + rmfServer: '$rmf_server_ver', + swaggerCodegen: '$swagger_ver', +}; + +EOF + +../../node_modules/.bin/prettier -w lib diff --git a/packages/api-client/lib/openapi/README.md b/packages/api-client/lib/openapi/README.md index 974a69fff..9c655dca3 100644 --- a/packages/api-client/lib/openapi/README.md +++ b/packages/api-client/lib/openapi/README.md @@ -3,23 +3,27 @@ This generator creates TypeScript/JavaScript client that utilizes [axios](https://github.com/axios/axios). The generated Node module can be used in the following environments: Environment -* Node.js -* Webpack -* Browserify + +- Node.js +- Webpack +- Browserify Language level -* ES5 - you must have a Promises/A+ library installed -* ES6 + +- ES5 - you must have a Promises/A+ library installed +- ES6 Module system -* CommonJS -* ES6 module system + +- CommonJS +- ES6 module system It can be used in both TypeScript and JavaScript. In TypeScript, the definition should be automatically resolved via `package.json`. ([Reference](http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html)) ### Building To build and compile the typescript sources to javascript use: + ``` npm install npm run build @@ -27,7 +31,7 @@ npm run build ### Publishing -First build the package then run ```npm publish``` +First build the package then run `npm publish` ### Consuming @@ -43,3 +47,4 @@ _unPublished (not recommended):_ ``` npm install PATH_TO_GENERATED_PACKAGE --save +``` diff --git a/packages/api-client/lib/openapi/api.ts b/packages/api-client/lib/openapi/api.ts index 528107b5a..7708f5f34 100644 --- a/packages/api-client/lib/openapi/api.ts +++ b/packages/api-client/lib/openapi/api.ts @@ -10,7 +10,7 @@ * NOTE: This class is auto generated by the swagger code generator program. * https://github.com/swagger-api/swagger-codegen.git * Do not edit the class manually. - */ export * from './apis/default-api'; + */ export * from './apis/building-api'; export * from './apis/doors-api'; export * from './apis/lifts-api'; export * from './apis/tasks-api'; diff --git a/packages/api-client/lib/openapi/apis/building-api.ts b/packages/api-client/lib/openapi/apis/building-api.ts new file mode 100644 index 000000000..9f0157265 --- /dev/null +++ b/packages/api-client/lib/openapi/apis/building-api.ts @@ -0,0 +1,139 @@ +/* tslint:disable */ +/* eslint-disable */ +/** + * FastAPI + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * OpenAPI spec version: 0.1.0 + * + * + * NOTE: This class is auto generated by the swagger code generator program. + * https://github.com/swagger-api/swagger-codegen.git + * Do not edit the class manually. + */ +import globalAxios, { AxiosPromise, AxiosInstance } from 'axios'; +import { Configuration } from '../configuration'; +// Some imports not used depending on template conditions +// @ts-ignore +import { BASE_PATH, COLLECTION_FORMATS, RequestArgs, BaseAPI, RequiredError } from '../base'; +import { BuildingMap } from '../models'; +/** + * BuildingApi - axios parameter creator + * @export + */ +export const BuildingApiAxiosParamCreator = function (configuration?: Configuration) { + return { + /** + * + * @summary Get Building Map + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getBuildingMapBuildingMapGet: async (options: any = {}): Promise => { + const localVarPath = `/building_map`; + // use dummy base URL string because the URL constructor only accepts absolute URLs. + const localVarUrlObj = new URL(localVarPath, 'https://example.com'); + let baseOptions; + if (configuration) { + baseOptions = configuration.baseOptions; + } + const localVarRequestOptions = { method: 'GET', ...baseOptions, ...options }; + const localVarHeaderParameter = {} as any; + const localVarQueryParameter = {} as any; + + const query = new URLSearchParams(localVarUrlObj.search); + for (const key in localVarQueryParameter) { + query.set(key, localVarQueryParameter[key]); + } + for (const key in options.query) { + query.set(key, options.query[key]); + } + localVarUrlObj.search = new URLSearchParams(query).toString(); + let headersFromBaseOptions = baseOptions && baseOptions.headers ? baseOptions.headers : {}; + localVarRequestOptions.headers = { + ...localVarHeaderParameter, + ...headersFromBaseOptions, + ...options.headers, + }; + + return { + url: localVarUrlObj.pathname + localVarUrlObj.search + localVarUrlObj.hash, + options: localVarRequestOptions, + }; + }, + }; +}; + +/** + * BuildingApi - functional programming interface + * @export + */ +export const BuildingApiFp = function (configuration?: Configuration) { + return { + /** + * + * @summary Get Building Map + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + async getBuildingMapBuildingMapGet( + options?: any, + ): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise> { + const localVarAxiosArgs = await BuildingApiAxiosParamCreator( + configuration, + ).getBuildingMapBuildingMapGet(options); + return (axios: AxiosInstance = globalAxios, basePath: string = BASE_PATH) => { + const axiosRequestArgs = { + ...localVarAxiosArgs.options, + url: basePath + localVarAxiosArgs.url, + }; + return axios.request(axiosRequestArgs); + }; + }, + }; +}; + +/** + * BuildingApi - factory interface + * @export + */ +export const BuildingApiFactory = function ( + configuration?: Configuration, + basePath?: string, + axios?: AxiosInstance, +) { + return { + /** + * + * @summary Get Building Map + * @param {*} [options] Override http request option. + * @throws {RequiredError} + */ + getBuildingMapBuildingMapGet(options?: any): AxiosPromise { + return BuildingApiFp(configuration) + .getBuildingMapBuildingMapGet(options) + .then((request) => request(axios, basePath)); + }, + }; +}; + +/** + * BuildingApi - object-oriented interface + * @export + * @class BuildingApi + * @extends {BaseAPI} + */ +export class BuildingApi extends BaseAPI { + /** + * + * @summary Get Building Map + * @param {*} [options] Override http request option. + * @throws {RequiredError} + * @memberof BuildingApi + */ + public getBuildingMapBuildingMapGet(options?: any) { + return BuildingApiFp(this.configuration) + .getBuildingMapBuildingMapGet(options) + .then((request) => request(this.axios, this.basePath)); + } +} diff --git a/packages/api-client/lib/openapi/tsconfig.json b/packages/api-client/lib/openapi/tsconfig.json index 2f27acb9f..8b2d062a1 100644 --- a/packages/api-client/lib/openapi/tsconfig.json +++ b/packages/api-client/lib/openapi/tsconfig.json @@ -6,16 +6,8 @@ "noImplicitAny": true, "outDir": "dist", "rootDir": ".", - "lib": [ - "es6", - "dom" - ], - "typeRoots": [ - "node_modules/@types" - ] + "lib": ["es6", "dom"], + "typeRoots": ["node_modules/@types"] }, - "exclude": [ - "dist", - "node_modules" - ] + "exclude": ["dist", "node_modules"] } diff --git a/packages/api-client/lib/version.ts b/packages/api-client/lib/version.ts new file mode 100644 index 000000000..0d00edf93 --- /dev/null +++ b/packages/api-client/lib/version.ts @@ -0,0 +1,8 @@ +// THIS FILE IS GENERATED +import { version as rmfModelVer } from 'rmf-models'; + +export const version = { + rmfModels: rmfModelVer, + rmfServer: 'bf4b8085153d73ab5094504e34fbac0d1fbeb6f4', + swaggerCodegen: '3.0.25', +}; diff --git a/packages/rmf-models/README.md b/packages/rmf-models/README.md deleted file mode 100644 index 26873494c..000000000 --- a/packages/rmf-models/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Generating models - -This most of this package contains generated code, simply run `generate-models.sh` to generate an updated version of the models. - -## Regarding side effects of pinning rmf-model version - -The advantage of pinning the version of rmf and rmf-server is that it releases the dependency of those packages. With pinning, there is no longer a need to have rmf sourced to build `rmf-models`, this allows dependents of `rmf-models` to free themselve of the transitive dependeny to rmf, this is especially for frontend only packages like `react-components` so that one can start contributing without all the hassle of building rmf. - -However, the biggest downside of pinning the version is that it makes it much harder to develop `rmf-models` dependencies concurrently with `rmf-models` itself. The reason is because we must never allow a PR of `rmf-models` that generates from anything other than the `main` branch. Because open-rmf use squash merges by default, any versions not from the `main` branch pinned to `rmf-models` will essentially be lost once the PR gets merged. - -Keep in mind that this is also true for `rmf-web` as well, so you CAN'T submit a PR that updates both `rmf-server` and `rmf-models`, as the version will be lost when that get merged. The `rmf-server` needs to be merged into `main` first before the PR for `rmf-models` can be submitted. diff --git a/packages/rmf-models/generate-models.js b/packages/rmf-models/generate-models.js index 8049a18de..c55b93809 100644 --- a/packages/rmf-models/generate-models.js +++ b/packages/rmf-models/generate-models.js @@ -29,12 +29,13 @@ console.log('generate models:'); path.join(tortoiseDir, 'GENERATED'), 'THIS DIRECTORY IS GENERATED, DO NOT EDIT!!', ); -})(); -execSync(`pipenv run python -m ts_ros -o lib/ros ${rmfMsgs.join(' ')}`, { - stdio: 'inherit', -}); -fs.writeFileSync( - path.join(__dirname, 'lib', 'ros', 'GENERATED'), - 'THIS DIRECTORY IS GENERATED, DO NOT EDIT!!', -); + execSync(`pipenv run python -m ts_ros -o lib/ros ${rmfMsgs.join(' ')}`, { + stdio: 'inherit', + }); + fs.writeFileSync( + path.join(__dirname, 'lib', 'ros', 'GENERATED'), + 'THIS DIRECTORY IS GENERATED, DO NOT EDIT!!', + ); + execSync(`../../node_modules/.bin/prettier -w lib/ros lib/tortoise`, { stdio: 'inherit' }); +})(); diff --git a/packages/rmf-models/generate-models.sh b/packages/rmf-models/generate-models.sh index da256a395..48dd664f4 100755 --- a/packages/rmf-models/generate-models.sh +++ b/packages/rmf-models/generate-models.sh @@ -1,12 +1,45 @@ #!/bin/bash set -e -if [[ -z $1 ]]; then - rmf_commit='main' -fi +function usage() { + echo "Usage: generate-models.sh" + echo "Options:" + echo " --rmf-tag " + echo " --rmf-server-ver " +} + +options=$(getopt -o '' -l rmf-tag:,rmf-server-ver: -- "$@") +eval set -- "$options" +while true; do + case "$1" in + --rmf-tag) + shift + rmf_tag=$1 + ;; + --rmf-server-ver) + shift + rmf_server_ver=$1 + ;; + --) + shift + break + ;; + esac + shift +done + script_dir=$(realpath $(dirname $0)) cd "$script_dir" +source ../../scripts/version.sh + +if [[ -z $rmf_tag ]]; then + rmf_tag='main' +fi +if [[ -z $rmf_server_ver ]]; then + rmf_server_ver=$(getVersion .) +fi + rmf_msgs=( 'rmf_building_map_msgs' 'rmf_charger_msgs' @@ -23,6 +56,7 @@ for pkg in ${rmf_msgs[@]}; do grep_args+=("-e$pkg") done +. /opt/ros/foxy/setup.bash if ros2 pkg list | grep "${grep_args[@]}"; then echo 'One or more rmf packages is already found in your env, you probably have rmf sourced.' echo 'This may cause problems when generating the models, please run this script in a new terminal without rmf sourced.' @@ -32,45 +66,32 @@ fi rm -rf build mkdir -p "$script_dir/build/rmf/src" cd "$script_dir/build/rmf/src" -git clone --depth 1 -b "$rmf_commit" "https://github.com/open-rmf/rmf_internal_msgs.git" -git clone --depth 1 -b "$rmf_commit" "https://github.com/open-rmf/rmf_building_map_msgs.git" -. /opt/ros/foxy/setup.bash -cd .. +git clone --depth 1 -b "$rmf_tag" "https://github.com/open-rmf/rmf_internal_msgs.git" +git clone --depth 1 -b "$rmf_tag" "https://github.com/open-rmf/rmf_building_map_msgs.git" +cd "$script_dir/build/rmf" colcon build --merge-install --cmake-args -DCMAKE_BUILD_TYPE=Release . install/setup.bash cd "$script_dir" -# TODO: update this when this branch is merged, chicken egg problem. -# cd "$script_dir/build" -# git clone --depth 1 -b main "https://github.com/open-rmf/rmf-web.git" node generate-models.js "${rmf_msgs[@]}" -function getVersion {( set -e - cd $1 - version=$(git tag --points-at HEAD) - if [[ -z $version ]]; then - version=$(git rev-parse HEAD) - fi - echo $version -)} - -rmf_internal_msgs_version=$(getVersion "build/rmf/src/rmf_internal_msgs") -rmf_building_map_msgs_version=$(getVersion "build/rmf/src/rmf_building_map_msgs") -rmf_server_version=$(getVersion .) +rmf_internal_msgs_ver=$(getVersion "build/rmf/src/rmf_internal_msgs") +rmf_building_map_msgs_ver=$(getVersion "build/rmf/src/rmf_building_map_msgs") cat << EOF > lib/version.ts // THIS FILE IS GENERATED export const version = { - rmfInternalMsgs: '$rmf_internal_msgs_version', - rmfBuildingMapMsgs: '$rmf_building_map_msgs_version', - rmfServer: '$rmf_server_version', + rmfInternalMsgs: '$rmf_internal_msgs_ver', + rmfBuildingMapMsgs: '$rmf_building_map_msgs_ver', + rmfServer: '$rmf_server_ver', }; + EOF echo '' echo 'versions:' -echo " rmf_internal_msgs: $rmf_internal_msgs_version" -echo " rmf_building_map_msgs: $rmf_building_map_msgs_version" -echo " rmf_server: $rmf_server_version" +echo " rmf_internal_msgs: $rmf_internal_msgs_ver" +echo " rmf_building_map_msgs: $rmf_building_map_msgs_ver" +echo " rmf_server: $rmf_server_ver" echo '' echo 'Successfully generated rmf-models' diff --git a/packages/rmf-models/lib/version.ts b/packages/rmf-models/lib/version.ts index 11fa1f847..7cd709e0d 100644 --- a/packages/rmf-models/lib/version.ts +++ b/packages/rmf-models/lib/version.ts @@ -2,5 +2,5 @@ export const version = { rmfInternalMsgs: '7bbeb211e9cadc1a12de1bb59c89938ba3972406', rmfBuildingMapMsgs: '58c2a1660596f77f09e39c808743491959608df4', - rmfServer: '76c328be04bbb22741627e2ccd56ecce971697d5', + rmfServer: 'bf4b8085153d73ab5094504e34fbac0d1fbeb6f4', }; diff --git a/scripts/version.sh b/scripts/version.sh new file mode 100644 index 000000000..8d5512065 --- /dev/null +++ b/scripts/version.sh @@ -0,0 +1,11 @@ +#!/bin/bash +set -e + +function getVersion {( set -e + cd $1 + version=$(git tag --points-at HEAD) + if [[ -z $version ]]; then + version=$(git rev-parse HEAD) + fi + echo $version +)}