diff --git a/README.md b/README.md index 9a4db8b..db60f27 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ # README This is the REST API server for the online Paco Ŝako chess variation front-end -provided by the [paco-sako](https://jessemcdonald.info/gogs/nybble/paco_sako) -package. The server stores game data in a SQLite3 database and exposes -interfaces for immediate queries, long-polling, and POST updates. The -listening port is configurable and HTTPS is supported with a certificate file. +provided by the [paco-sako](https://jessemcdonald.info/gogs/nybble/paco_sako) package. +The server stores game data in a SQLite3 database +and exposes interfaces for immediate queries, long-polling, and POST updates. +The listening port is configurable and HTTPS is supported with a certificate file. ## Invocation @@ -12,68 +12,74 @@ listening port is configurable and HTTPS is supported with a certificate file. node ./server.js [PORT] ``` +or + +``` +npm start [PORT] +``` + ## Environment Variables ### `OPENSHIFT_NODEJS_PORT`, `VCAP_APP_PORT`, or `PORT` -If any of these variables are defined, the first one encountered determines -the listening port, overriding any port specified on the command line. The -default port is 8765 if no environment variable is defined and no port is -given on the command line. +If any of these variables are defined +then the first one encountered determines the listening port, +overriding any port specified on the command line. +The default port is 8765 if no environment variable is defined +and no port is given on the command line. -### `HTTPS_KEY`, `HTTPS_CERT` +### `HTTPS_KEY` and `HTTPS_CERT` -If the `HTTPS_KEY` environment variable is defined then the server operates in -HTTPS mode using the key found in the file named by `HTTPS_KEY` and the -certificate found in the file named by `HTTPS_CERT`. If `HTTPS_KEY` is set -then `HTTPS_CERT` is also required. +If the `HTTPS_KEY` environment variable is defined +then the server operates in HTTPS mode +using the key found in the file named by `HTTPS_KEY` +and the certificate found in the file named by `HTTPS_CERT`. +If `HTTPS_KEY` is set then `HTTPS_CERT` is also required. ## JSON Schema -Most APIs either accept or return a JSON "game data" object with some or all -of the following fields: +Most APIs either accept or return a JSON "game data" object +with some or all of the following fields: -* `gameId`: String. Sixteen hexadecimal characters. The randomly-generated - code which uniquely identifies a game. +* `gameId`: String. Sixteen hexadecimal characters. + The randomly-generated code which uniquely identifies a game. * `lightName`: String. The name of the player controlling the light pieces. * `darkName`: String. The name of the player controlling the dark pieces. -* `moves`: Integer. The number of partial *or* completed *turns* in the current - game. Also the number of times the light player has started a move. (The use - of the name `moves` rather than `turns` is a historical artifact.) +* `moves`: Integer. The number of partial *or* completed *turns* in the current game. + Also the number of times the light player has started a move. + (The use of the name `moves` rather than `turns` is a historical artifact.) -* `status`: String. A short string which describes the current state of the - game, for example the current player if the game is ongoing or the winner - otherwise. This string appers in the game selection list. +* `status`: String. A short string which describes the current state of the game, + for example the current player if the game is ongoing or the winner otherwise. + This string appers in the game selection list. -* `timestamp`: Integer. The UTC time in milliseconds (`+new Date()`) of the - most recent move. Typically the same as the `timestamp` metadata associated - with the last move in `board.past`, or the time when the metadata was most - recently updated if there are no moves. The timestamp can decrease, for - example in response to a player undoing a move. +* `timestamp`: Integer. The UTC time in milliseconds of the most recent move. + Typically the same as the `timestamp` metadata for the last move in `board.past`, + or the time when the metadata was most recently updated if there are no moves. + The timestamp can decrease, for example in response to a player undoing a move. -* `board`: Object. An arbitrary JSON object provided by the front-end to - describe the current state of the game. The object is not validated by the - server at present but it typically includes two fields, `past` and `future`, - which are arrays of objects respectively representing the moves completed - thus far and (in reverse order) any moves which were undone, to support the - redo operation. This object is stored in the database as a JSON-encoded - string. +* `board`: Object. An arbitrary JSON object provided by the front-end + to describe the current state of the game. + The object is not validated by the server at present + but it typically includes two fields, `past` and `future`, + which are arrays of objects respectively representing the moves completed thus far + and (in reverse order) any moves which were undone, to support the redo operation. + This object is stored in the database as a JSON-encoded string. -* `modified`: Integer. The modification timestamp of the record, as determined - by the server. This is normally a UTC time in milliseconds but the server - adjusts the value to ensure that updates have modification times which are - strictly greater than any modification times previously stored in the - database. +* `modified`: Integer. The modification time of the record as determined by the server. + This is normally a UTC time in milliseconds but the server adjusts the value + to ensure that updates have modification times which are strictly greater than + any modification times previously stored in the database. -The "metadata" fields are all the fields listed above except `board`. The -`board` field is potentially large and consequently is omitted from the -responses for certain APIs. +The "metadata" fields are all the fields listed above except `board`. +The `board` field is potentially large and consequently is omitted +from the responses for certain APIs. -Fields which are either NULL or equal to an empty string are not included in -game objects returned from the REST APIs. +Fields which are either NULL or equal to an empty string are not included +in game objects returned from the REST APIs. The following data is stored in the database but not included in any REST API: @@ -84,33 +90,41 @@ The following data is stored in the database but not included in any REST API: ### `GET /pacosako/api/games` -Returns the list of active games. A game is considered "active" if the -`timestamp` field indicates that the game was started or the last move was -played within the past two weeks, according to the server's clock. The -successful JSON response consists of two fields, `games` which is an array of -game objects in descending order by their `timestamp` fields, and `modified` -which is the maximum of the `modified` field for any of the games in the -`games` array. The objects in the `games` array include all of the game object -fields described above *except* the `board` field. +Returns the list of active games. +A game is considered "active" if the `timestamp` field indicates that +either the game was started or the last move was played +within the past two weeks according to the server's clock. +The successful JSON response consists of two fields, +`games` which is an array of game objectsi +in descending order by their `timestamp` fields, +and `modified` which is the maximum value of the `modified` fields +of all of the games in the `games` array, +or zero if the array is empty. +The objects in the `games` array include +all of the game object fields described above +*except* the `board` field. ### `GET /pacosako/api/games/poll/:afterTime` Parameters: -* `afterTime`: Integer. Any record with a `modified` field less than or equal - to this value is excluded from the results. +* `afterTime`: Integer. + Any record with a `modified` field less than or equal to this value + is excluded from the results. -Equivalent to the `GET /pacosako/api/games` API with two exceptions. First, it -excludes games with older `modified` times from the results. Second, if there -are no results which match this criteria then the server waits up to one -minute for the situation to change before responding with a 204 status code. -It is expected that the client will respond to a 204 status by repeating the -request. If a game is updated during the waiting period then the server will -respond immediately with the new information. +Equivalent to the `GET /pacosako/api/games` API with two exceptions. +First, it excludes games with older `modified` times from the results. +Second, if there are no results which match this criteria +then the server waits up to one minute for the situation to change +before responding with a 204 status code. +It is expected that the client will respond to a 204 status +by repeating the request. +If a game is updated during the waiting period +then the server will respond immediately with the new information. -The `afterTime` parameter will normally match the `modified` field from the -most recent successful response to either `GET /pacosako/api/games` or `GET -/pacosako/api/games/poll/:afterTime`. +The `afterTime` parameter will normally match the `modified` field +from the most recent successful response to either +`GET /pacosako/api/games` or `GET /pacosako/api/games/poll/:afterTime`. ### `GET /pacosako/api/game/:gameId` @@ -119,8 +133,8 @@ Parameters: * `gameId`: String. Identifies the game object to be returned. On success this API returns the complete game object for the given `gameId`, -which must be a 16-character hexadecimal string. If there is no record -matching the given gameId then a 404 status code is returned. +which must be a 16-character hexadecimal string. +If there is no record matching the given gameId then a 404 status code is returned. ### `GET /pacosako/api/meta/:gameId` @@ -133,22 +147,23 @@ Parameters: * `gameId`: String. Identifies the game object to be returned. -* `afterTime`: Integer. The response must be a game object with a `modified` - field strictly greater than this value. +* `afterTime`: Integer. The response must be a game object + with a `modified` field strictly greater than this value. -Equivalent to the `GET /pacosako/api/game/:gameId` API except that if there is -no record with a matching `gameId` or the record has a `modified` field less -than or equal to the `afterTime` parameter then the server waits up to one -minute for the situation to change before responding with a 204 status code. -It is expected that the client will respond to a 204 status by repeating the -request. If the game is created or updated during the waiting period then the -server will respond immediately with the new information. Unlike the -non-polling version, this API does not return a 404 status code when the -`gameId` does not exist. +Equivalent to the `GET /pacosako/api/game/:gameId` API except that +if there is no record with a matching `gameId` +or the record has a `modified` field less than or equal to the `afterTime` parameter +then the server waits up to one minute for the situation to change +before responding with a 204 status code. +It is expected that the client will respond to a 204 status by repeating the request. +If the game is created or updated during the waiting period +then the server will respond immediately with the new information. +Unlike the non-polling version, +this API does not return a 404 status code when the `gameId` does not exist. -The `afterTime` parameter will normally match the `modified` field from the -most recent successful response to either `GET /pacosako/api/game/:gameId` or -`GET /pacosako/api/game/:gameId/poll/:afterTime`. +The `afterTime` parameter will normally match the `modified` field +from the most recent successful response to either +`GET /pacosako/api/game/:gameId` or `GET /pacosako/api/game/:gameId/poll/:afterTime`. ### `GET /pacosako/api/meta/:gameId/poll/:afterTime` @@ -161,25 +176,33 @@ Parameters: * `gameId`: String. Identifies the game object to be updated. -The request body for this API should consist of a subset of a game object -which includes the `modified` field and at least one other field to be -updated. The `modified` field in the request must match the *current* version -of the record in the database for the update to be successful; this serves as -a form of locking to prevent race conditions between multiple clients updating -the same game record. The `modified` field of the new version of the record on -success will be determined by the server. +The JSON-encoded request body for this API should consist of a subset of a game object +which includes the `modified` field and at least one other field to be updated. +The `modified` field in the request must match +the *current* version of the record in the database +for the update to be successful, if such a record exists; +this serves as a form of locking to prevent race conditions +between multiple clients updating the same game record. +The `modified` field of the new version of the record on success +will be determined by the server. +If there is no existing version of the record then +value of the `modified` field in the request is not used; +however, the field is still required. +It is recommended that a `modified` value of zero be used +when initializing a new game +since this value is guaranteed not to match any existing game record. -A 400 status code will be returned if the request body does not follow the -expected schema. If the `modified` field in the request does not match the -`modified` field in the database *and* the value of any other field in the -request does not match the current version of the data in the database then a -409 response is returned with a `message` string field describing the error -and the `modified` field from the current version of the record in the -database. Otherwise the POST request succeeds with a status code of 200 and -the response body consists of a `success` field with the value `true` and the -`modified` field of the new version of the record in the database. +A 400 status will be returned if the request body does not follow the expected schema. +If the `modified` field does not match the `modified` field in the database +*and* the value of any other field in the request does not match +the current version of the data in the database +then a 409 response is returned with a `message` string field describing the error +and the `modified` field from the current version of the record in the database. +Otherwise the POST request succeeds with a status code of 200 +and the response body consists of a `success` field with the value `true` +and the `modified` field of the new version of the record. ### `POST /pacosako/api/meta/:gameId` -This is an alias for the `POST /pacosako/api/game/:gameId` API. Either API can -be used to update any field, including `board`. +This is an alias for the `POST /pacosako/api/game/:gameId` API. +Either API can be used to update any field, including `board`.