Skip to content

Commit

Permalink
Revamp site for December 2024
Browse files Browse the repository at this point in the history
This fixes a bunch of dependencies, upgrades the Node version, and fixes CI.

## Dependency updates

- Upgrade React to v18
- Upgrade from material-ui v4 to mui 6 (lots of breaking API changes / incompatibility)
- Upgraded to react-router v7 (again, many breaking changes)
- Update Stripe client v1 -> v5
- Update chart.js v3 -> v4
- Update clsx v1 -> v2
- Update firebase v9 -> v11
- Update react-chartjs-2 v4 -> v5
- Update Prettier v2 -> v3
- Update firebase-admin v9 -> v13
- Update firebase-functions v3 -> v6
- Update Stripe server v8 -> v17
  • Loading branch information
ekzhang committed Dec 21, 2024
1 parent 781e031 commit fd1aa82
Show file tree
Hide file tree
Showing 57 changed files with 7,396 additions and 4,239 deletions.
24 changes: 12 additions & 12 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ jobs:
name: Format
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"

- run: npm ci

Expand All @@ -27,11 +27,11 @@ jobs:
name: Lint and Test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"

- run: npm ci

Expand All @@ -43,11 +43,11 @@ jobs:
name: Cloud Functions
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"

- run: npm ci
working-directory: functions
Expand All @@ -66,11 +66,11 @@ jobs:
success() && github.event_name == 'push' && github.repository_owner ==
'ekzhang'
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"

- run: npm ci

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ jobs:
runs-on: ubuntu-latest
if: ${{ startsWith(github.ref, 'refs/tags/v') }}
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4

- uses: actions/setup-node@v2
- uses: actions/setup-node@v4
with:
node-version: "16"
node-version: "20"

- run: npm ci

Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
build/
.vscode/
.DS_Store


Expand Down
10 changes: 5 additions & 5 deletions functions/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^9.11.1",
"firebase-functions": "^3.19.0",
"stripe": "^8.209.0"
"firebase-admin": "^13.0.2",
"firebase-functions": "^6.2.0",
"stripe": "^17.5.0"
},
"devDependencies": {
"firebase-functions-test": "^0.3.3",
"firebase-functions-test": "^3.4.0",
"tslint": "^6.1.3",
"typescript": "~4.4.4"
"typescript": "~5.7.2"
},
"private": true
}
4 changes: 2 additions & 2 deletions functions/src/game.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ function replayEventNormal(deck: Set<string>, event: GameEvent) {
function replayEventChain(
history: GameEvent[],
deck: Set<string>,
event: GameEvent
event: GameEvent,
) {
const { c1, c2, c3 } = event;

Expand Down Expand Up @@ -153,7 +153,7 @@ function replayEventUltra(deck: Set<string>, event: GameEvent) {
*/
export function replayEvents(
gameData: admin.database.DataSnapshot,
gameMode: GameMode
gameMode: GameMode,
) {
const events: GameEvent[] = [];
gameData.child("events").forEach((e) => {
Expand Down
38 changes: 19 additions & 19 deletions functions/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ export const finishGame = functions.https.onCall(async (data, context) => {
throw new functions.https.HttpsError(
"invalid-argument",
"The function must be called with " +
"argument `gameId` to be finished at `/games/:gameId`."
"argument `gameId` to be finished at `/games/:gameId`.",
);
}
if (!context.auth) {
throw new functions.https.HttpsError(
"failed-precondition",
"The function must be called while authenticated."
"The function must be called while authenticated.",
);
}

Expand All @@ -52,7 +52,7 @@ export const finishGame = functions.https.onCall(async (data, context) => {
if (!gameSnap.exists()) {
throw new functions.https.HttpsError(
"not-found",
`The game with gameId ${gameId} was not found in the database.`
`The game with gameId ${gameId} was not found in the database.`,
);
}

Expand All @@ -63,7 +63,7 @@ export const finishGame = functions.https.onCall(async (data, context) => {
if (findSet(Array.from(deck), gameMode, lastSet)) {
throw new functions.https.HttpsError(
"failed-precondition",
"The requested game has not yet ended."
"The requested game has not yet ended.",
);
}

Expand Down Expand Up @@ -139,7 +139,7 @@ export const finishGame = functions.https.onCall(async (data, context) => {
});
// Save these values for use in rating calculation
userStats[player] = result.snapshot.val();
})
}),
);

// If the game is solo, we skip rating calculation.
Expand Down Expand Up @@ -209,7 +209,7 @@ export const createGame = functions.https.onCall(async (data, context) => {
throw new functions.https.HttpsError(
"invalid-argument",
"The function must be called with " +
"argument `gameId` to be created at `/games/:gameId`."
"argument `gameId` to be created at `/games/:gameId`.",
);
}
if (
Expand All @@ -219,13 +219,13 @@ export const createGame = functions.https.onCall(async (data, context) => {
throw new functions.https.HttpsError(
"invalid-argument",
"The function must be called with " +
'argument `access` given value "public" or "private".'
'argument `access` given value "public" or "private".',
);
}
if (!context.auth) {
throw new functions.https.HttpsError(
"failed-precondition",
"The function must be called while authenticated."
"The function must be called while authenticated.",
);
}

Expand All @@ -241,8 +241,8 @@ export const createGame = functions.https.onCall(async (data, context) => {

const recentGames = await Promise.all(
Object.keys(recentGameIds.val() || {}).map((recentGameId) =>
admin.database().ref(`games/${recentGameId}`).once("value")
)
admin.database().ref(`games/${recentGameId}`).once("value"),
),
);

let unfinishedGames = 0;
Expand All @@ -265,7 +265,7 @@ export const createGame = functions.https.onCall(async (data, context) => {
) {
throw new functions.https.HttpsError(
"resource-exhausted",
"Too many unfinished public games were recently created."
"Too many unfinished public games were recently created.",
);
}
return {
Expand All @@ -283,7 +283,7 @@ export const createGame = functions.https.onCall(async (data, context) => {
if (!committed) {
throw new functions.https.HttpsError(
"already-exists",
"The requested `gameId` already exists."
"The requested `gameId` already exists.",
);
}

Expand All @@ -296,21 +296,21 @@ export const createGame = functions.https.onCall(async (data, context) => {
updates.push(
admin.database().ref(`gameData/${gameId}`).set({
deck: generateDeck(),
})
}),
);
updates.push(
admin
.database()
.ref("stats/gameCount")
.transaction((count) => (count || 0) + 1)
.transaction((count) => (count || 0) + 1),
);
if (access === "public") {
updates.push(
admin
.database()
.ref("publicGames")
.child(gameId)
.set(snapshot?.child("createdAt").val())
.set(snapshot?.child("createdAt").val()),
);
}

Expand All @@ -323,23 +323,23 @@ export const customerPortal = functions.https.onCall(async (data, context) => {
if (!context.auth) {
throw new functions.https.HttpsError(
"failed-precondition",
"This function must be called while authenticated."
"This function must be called while authenticated.",
);
}

const user = await admin.auth().getUser(context.auth.uid);
if (!user.email) {
throw new functions.https.HttpsError(
"failed-precondition",
"This function must be called by an authenticated user with email."
"This function must be called by an authenticated user with email.",
);
}

const customerResponse = await stripe.customers.list({ email: user.email });
if (!customerResponse.data.length) {
throw new functions.https.HttpsError(
"not-found",
`A subscription with email ${user.email} was not found.`
`A subscription with email ${user.email} was not found.`,
);
}

Expand Down Expand Up @@ -399,7 +399,7 @@ export const handleStripe = functions.https.onRequest(async (req, res) => {
) {
const subscription = event.data.object as Stripe.Subscription;
const { email } = (await stripe.customers.retrieve(
subscription.customer as string
subscription.customer as string,
)) as Stripe.Response<Stripe.Customer>;

if (email) {
Expand Down
Loading

0 comments on commit fd1aa82

Please sign in to comment.