Webatrice: improve prebuild steps and add .env configs (#4564)

* create .env file for server configuration

* render client version

* automate env file

* add prestart command

* create server-props.json instead of using .env

* automate master proto file

Co-authored-by: Jeremy Letto <jeremy.letto@datasite.com>
This commit is contained in:
Jeremy Letto 2022-02-12 17:58:47 -06:00 committed by GitHub
parent 408a13c937
commit 88b861d632
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 119 additions and 21175 deletions

1
webclient/.env Normal file
View file

@ -0,0 +1 @@
# Future template for server admin configuration

View file

@ -0,0 +1 @@
ESLINT_NO_DEV_ERRORS=true

View file

@ -0,0 +1 @@
DISABLE_ESLINT_PLUGIN=true

1
webclient/.env.test Normal file
View file

@ -0,0 +1 @@
CI=true

View file

@ -5,6 +5,10 @@
/.pnp /.pnp
.pnp.js .pnp.js
# generated ./src files
/src/proto-files.json
/src/server-props.json
# testing # testing
/coverage /coverage

View file

@ -1,3 +0,0 @@
#!/bin/bash
robocopy /E ../common/pb/. ./public/pb/
robocopy /E ../cockatrice/resources/countries/. ./src/images/countries

View file

@ -1,3 +0,0 @@
#!/bin/bash
cp -a ../common/pb/. ./public/pb/
cp -a ../cockatrice/resources/countries/. ./src/images/countries

21023
webclient/package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -33,12 +33,11 @@
"typescript": "^4.4.4" "typescript": "^4.4.4"
}, },
"scripts": { "scripts": {
"postinstall": "run-script-os", "prebuild": "node prebuild.js",
"postinstall:windows": "powershell .\\copy_shared_files.ps1", "prestart": "node prebuild.js",
"postinstall:default": "./copy_shared_files.sh", "build": "react-scripts build",
"start": "cross-env ESLINT_NO_DEV_ERRORS=true react-scripts start", "start": "react-scripts start",
"build": "cross-env DISABLE_ESLINT_PLUGIN=true react-scripts build", "test": "react-scripts test",
"test": "cross-env CI=true react-scripts test",
"test:watch": "react-scripts test", "test:watch": "react-scripts test",
"eject": "react-scripts eject", "eject": "react-scripts eject",
"lint": "eslint \"./**/*.{ts,tsx}\"", "lint": "eslint \"./**/*.{ts,tsx}\"",
@ -82,9 +81,8 @@
"@types/redux-form": "^8.3.3", "@types/redux-form": "^8.3.3",
"@typescript-eslint/eslint-plugin": "^5.3.1", "@typescript-eslint/eslint-plugin": "^5.3.1",
"@typescript-eslint/parser": "^5.3.1", "@typescript-eslint/parser": "^5.3.1",
"cross-env": "^7.0.3",
"eslint": "^7.32.0", "eslint": "^7.32.0",
"identity-obj-proxy": "^3.0.0", "fs-extra": "^10.0.0",
"run-script-os": "^1.1.6" "identity-obj-proxy": "^3.0.0"
} }
} }

58
webclient/prebuild.js Normal file
View file

@ -0,0 +1,58 @@
const fse = require('fs-extra');
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const protoFilesDir = './public/pb';
const serverPropsFile = './src/server-props.json';
const masterProtoFile = './src/proto-files.json';
const sharedFiles = [
['../common/pb', protoFilesDir],
['../cockatrice/resources/countries', './src/images/countries'],
];
(async () => {
// make sure these files finish copying before master file is created
await copySharedFiles();
createMasterProtoFile();
createServerProps();
})();
async function copySharedFiles() {
try {
return await Promise.all(sharedFiles.map(([src, dest]) => fse.copy(src, dest, { overwrite: true })));
} catch (e) {
console.error(e);
process.exitCode = 1;
}
}
function createMasterProtoFile() {
try {
fse.readdir(protoFilesDir, (err, files) => {
if (err) throw err;
fse.outputFile(masterProtoFile, JSON.stringify(files.filter(file => /\.proto$/.test(file))));
});
} catch (e) {
console.error(e);
process.exitCode = 1;
}
}
async function createServerProps() {
try {
fse.outputFile(serverPropsFile, JSON.stringify({
REACT_APP_VERSION: await getCommitHash(),
}));
} catch (e) {
console.error(e);
process.exitCode = 1;
}
}
async function getCommitHash() {
return (await exec('git rev-parse HEAD')).stdout.trim();
}

View file

@ -12,7 +12,7 @@ import { RegistrationDialog, RequestPasswordResetDialog, ResetPasswordDialog, Ac
import { LoginForm } from 'forms'; import { LoginForm } from 'forms';
import { useReduxEffect, useFireOnce } from 'hooks'; import { useReduxEffect, useFireOnce } from 'hooks';
import { Images } from 'images'; import { Images } from 'images';
import { HostDTO } from 'services'; import { HostDTO, serverProps } from 'services';
import { RouteEnum, WebSocketConnectOptions, getHostPort } from 'types'; import { RouteEnum, WebSocketConnectOptions, getHostPort } from 'types';
import { ServerSelectors, ServerTypes } from 'store'; import { ServerSelectors, ServerTypes } from 'store';
@ -256,9 +256,16 @@ const Login = ({ state, description }: LoginProps) => {
<span>Not registered yet?</span> <span>Not registered yet?</span>
<Button color="primary" onClick={openRegistrationDialog}>Create an account</Button> <Button color="primary" onClick={openRegistrationDialog}>Create an account</Button>
</div> </div>
<Typography variant="subtitle2" className="login-footer__copyright"> <Typography variant="subtitle2">
Cockatrice is an open source project. { new Date().getUTCFullYear() } Cockatrice is an open source project. { new Date().getUTCFullYear() }
</Typography> </Typography>
{
serverProps.REACT_APP_VERSION && (
<Typography variant="subtitle2">
Version: { serverProps.REACT_APP_VERSION }
</Typography>
)
}
</div> </div>
</div> </div>
<div className="login-content__description"> <div className="login-content__description">

View file

@ -0,0 +1,9 @@
import props from '../server-props.json';
class ServerProps {
get REACT_APP_VERSION() {
return props?.REACT_APP_VERSION;
}
}
export const serverProps = new ServerProps();

View file

@ -1,2 +1,3 @@
export * from './CardImporterService'; export * from './CardImporterService';
export * from './ServerProps';
export * from './dexie'; export * from './dexie';

View file

@ -1,156 +0,0 @@
const ProtoFiles = [
'admin_commands.proto',
'card_attributes.proto',
'color.proto',
'command_attach_card.proto',
'command_change_zone_properties.proto',
'command_concede.proto',
'command_create_arrow.proto',
'command_create_counter.proto',
'command_create_token.proto',
'command_deck_del.proto',
'command_deck_del_dir.proto',
'command_deck_download.proto',
'command_deck_list.proto',
'command_deck_new_dir.proto',
'command_deck_select.proto',
'command_deck_upload.proto',
'command_del_counter.proto',
'command_delete_arrow.proto',
'command_draw_cards.proto',
'command_dump_zone.proto',
'command_flip_card.proto',
'command_game_say.proto',
'command_inc_card_counter.proto',
'command_inc_counter.proto',
'command_kick_from_game.proto',
'command_leave_game.proto',
'command_move_card.proto',
'command_mulligan.proto',
'command_next_turn.proto',
'command_ready_start.proto',
'command_replay_delete_match.proto',
'command_replay_download.proto',
'command_replay_list.proto',
'command_replay_modify_match.proto',
'command_reveal_cards.proto',
'command_roll_die.proto',
'command_set_active_phase.proto',
'command_set_card_attr.proto',
'command_set_card_counter.proto',
'command_set_counter.proto',
'command_set_sideboard_lock.proto',
'command_set_sideboard_plan.proto',
'command_shuffle.proto',
'command_undo_draw.proto',
'commands.proto',
'context_concede.proto',
'context_connection_state_changed.proto',
'context_deck_select.proto',
'context_move_card.proto',
'context_mulligan.proto',
'context_ping_changed.proto',
'context_ready_start.proto',
'context_set_sideboard_lock.proto',
'context_undo_draw.proto',
'event_add_to_list.proto',
'event_attach_card.proto',
'event_change_zone_properties.proto',
'event_connection_closed.proto',
'event_create_arrow.proto',
'event_create_counter.proto',
'event_create_token.proto',
'event_del_counter.proto',
'event_delete_arrow.proto',
'event_destroy_card.proto',
'event_draw_cards.proto',
'event_dump_zone.proto',
'event_flip_card.proto',
'event_game_closed.proto',
'event_game_host_changed.proto',
'event_game_joined.proto',
'event_game_say.proto',
'event_game_state_changed.proto',
'event_join.proto',
'event_join_room.proto',
'event_kicked.proto',
'event_leave.proto',
'event_leave_room.proto',
'event_list_games.proto',
'event_list_rooms.proto',
'event_move_card.proto',
'event_notify_user.proto',
'event_player_properties_changed.proto',
'event_remove_from_list.proto',
'event_replay_added.proto',
'event_reveal_cards.proto',
'event_roll_die.proto',
'event_room_say.proto',
'event_server_complete_list.proto',
'event_server_identification.proto',
'event_server_message.proto',
'event_server_shutdown.proto',
'event_set_active_phase.proto',
'event_set_active_player.proto',
'event_set_card_attr.proto',
'event_set_card_counter.proto',
'event_set_counter.proto',
'event_shuffle.proto',
'event_user_joined.proto',
'event_user_left.proto',
'event_user_message.proto',
'game_commands.proto',
'game_event.proto',
'game_event_container.proto',
'game_event_context.proto',
'game_replay.proto',
'isl_message.proto',
'moderator_commands.proto',
'move_card_to_zone.proto',
'response.proto',
'response_activate.proto',
'response_adjust_mod.proto',
'response_ban_history.proto',
'response_deck_download.proto',
'response_deck_list.proto',
'response_deck_upload.proto',
'response_dump_zone.proto',
'response_forgotpasswordrequest.proto',
'response_get_games_of_user.proto',
'response_get_user_info.proto',
'response_join_room.proto',
'response_list_users.proto',
'response_login.proto',
'response_password_salt.proto',
'response_register.proto',
'response_replay_download.proto',
'response_replay_list.proto',
'response_viewlog_history.proto',
'response_warn_history.proto',
'response_warn_list.proto',
'room_commands.proto',
'room_event.proto',
'server_message.proto',
'serverinfo_arrow.proto',
'serverinfo_ban.proto',
'serverinfo_card.proto',
'serverinfo_cardcounter.proto',
'serverinfo_chat_message.proto',
'serverinfo_counter.proto',
'serverinfo_deckstorage.proto',
'serverinfo_game.proto',
'serverinfo_gametype.proto',
'serverinfo_player.proto',
'serverinfo_playerping.proto',
'serverinfo_playerproperties.proto',
'serverinfo_replay.proto',
'serverinfo_replay_match.proto',
'serverinfo_room.proto',
'serverinfo_user.proto',
'serverinfo_warning.proto',
'serverinfo_zone.proto',
'session_commands.proto',
'session_event.proto',
];
export default ProtoFiles;

View file

@ -1,10 +1,10 @@
import protobuf from 'protobufjs'; import protobuf from 'protobufjs';
import ProtoFiles from '../ProtoFiles';
import { WebClient } from '../WebClient';
import { RoomEvents, SessionEvents } from '../events'; import { RoomEvents, SessionEvents } from '../events';
import { SessionPersistence } from '../persistence'; import { SessionPersistence } from '../persistence';
import { WebClient } from '../WebClient';
import ProtoFiles from '../../proto-files.json';
export interface ProtobufEvents { export interface ProtobufEvents {
[event: string]: Function; [event: string]: Function;