Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

impl ts-check #1709

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions .github/scripts/generate-metadata.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Astro integration that generatest the game/metadata.json
*
* How it works:
* 1. It walks/scans the ./games/ directory
* 2. It searches each file for metadata, if anything isn't found it halts the build/dev
* 3. If found it checks if everything is valid
* 4. Write metadata.json
*/
import fs from "fs";

/**
* An object containing all of the regex expressions that can be used
*/
const regexExpr = {
title: /@title: (.+)/,
author: /@author: (.+)/,
tags: /@tags: (.+)/,
img: /@img: (.+)/,
addedOn: /@addedOn: (.+)/,
};

/**
* Checks if the metadata is valid
*
* TODO!
*/
const isMetadataValid = (_) => {
return true;
};

const metadata = [];
/**
* Walks the ./games/ directory and returns all of the .js files
*/
const walk = () => {
const files = fs.readdirSync("./games/");
return files.filter((file) => file.endsWith(".js"));
};

// Loop for each game
walk().forEach((gameFile) => {
process.stdout.write(`[${gameFile}] Looking for metadata...`);

const fileData = fs.readFileSync(`./games/${gameFile}`).toString();

// Extract the file data
const title = regexExpr.title.exec(fileData);
const author = regexExpr.author.exec(fileData);
const tags = regexExpr.tags.exec(fileData);
const img = regexExpr.img.exec(fileData);
const addedOn = regexExpr.addedOn.exec(fileData);

// Check if all of the fields are defined
if (title && author && tags && img && addedOn && tags[1]) {
// Create a meta entry
const metaEntry = {
filename: gameFile.replace(".js", ""),
title: title[1],
author: author[1],
tags: JSON.parse(tags[1].replaceAll("'", '"')), // Replace all ' with " in order for compatibility issues
img: img[1] == '""' ? "" : img[1],
addedOn: addedOn[1],
};

metadata.push(metaEntry);
console.log(" OK!");
} else {
console.log(" ERR!");
throw Error("A game metadata field is undefined!");
}
});

process.stdout.write("[METADATA] Writing metadata file...");
if (isMetadataValid(metadata)) {
fs.writeFileSync("./games/metadata.json", JSON.stringify(metadata));
console.log(" OK!");
} else {
console.log(" ERR!");
}
27 changes: 27 additions & 0 deletions .github/workflows/ts-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: TypeScript Check

on:
pull_request:
types: [opened, reopened, edited]

jobs:
# Test job
build:
runs-on: ubuntu-latest
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Install Node
uses: actions/setup-node@v4
with:
node-version: 20.x

- name: Install Dependencies
run: |
yarn install

- name: Build Project
run: |
node .github/scripts/generate-metadata.js
yarn tsc --noEmit
80 changes: 80 additions & 0 deletions generate-meta.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Astro integration that generatest the game/metadata.json
*
* How it works:
* 1. It walks/scans the ./games/ directory
* 2. It searches each file for metadata, if anything isn't found it halts the build/dev
* 3. If found it checks if everything is valid
* 4. Write metadata.json
*/
import fs from "fs";

/**
* An object containing all of the regex expressions that can be used
*/
const regexExpr = {
title: /@title: (.+)/,
author: /@author: (.+)/,
tags: /@tags: (.+)/,
img: /@img: (.+)/,
addedOn: /@addedOn: (.+)/,
};

/**
* Checks if the metadata is valid
*
* TODO!
*/
const isMetadataValid = (_) => {
return true;
};

const metadata = [];
/**
* Walks the ./games/ directory and returns all of the .js files
*/
const walk = () => {
const files = fs.readdirSync("./games/");
return files.filter((file) => file.endsWith(".js"));
};

// Loop for each game
walk().forEach((gameFile) => {
process.stdout.write(`[${gameFile}] Looking for metadata...`);

const fileData = fs.readFileSync(`./games/${gameFile}`).toString();

// Extract the file data
const title = regexExpr.title.exec(fileData);
const author = regexExpr.author.exec(fileData);
const tags = regexExpr.tags.exec(fileData);
const img = regexExpr.img.exec(fileData);
const addedOn = regexExpr.addedOn.exec(fileData);

// Check if all of the fields are defined
if (title && author && tags && img && addedOn && tags[1]) {
// Create a meta entry
const metaEntry = {
filename: gameFile.replace(".js", ""),
title: title[1],
author: author[1],
tags: JSON.parse(tags[1].replaceAll("'", '"')), // Replace all ' with " in order for compatibility issues
img: img[1] == '""' ? "" : img[1],
addedOn: addedOn[1],
};

metadata.push(metaEntry);
console.log(" OK!");
} else {
console.log(" ERR!");
throw Error("A game metadata field is undefined!");
}
});

process.stdout.write("[METADATA] Writing metadata file...");
if (isMetadataValid(metadata)) {
fs.writeFileSync("./games/metadata.json", JSON.stringify(metadata));
console.log(" OK!");
} else {
console.log(" ERR!");
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"@types/esprima": "^4.0.3",
"@types/grecaptcha": "^3.0.4",
"@types/js-beautify": "^1.14.3",
"@types/node-statsd": "^0.1.6",
"@types/three": "^0.149.0",
"@types/throttle-debounce": "^5.0.0",
"@types/w3c-web-serial": "^1.0.3"
Expand Down
12 changes: 6 additions & 6 deletions src/components/big-interactive-pages/login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,11 @@ export default function Login({ session, email, to }: LoginProps) {
<h1>Log In to Sprig</h1>
{auth.stage.value === 'EMAIL' ? (<>
<p>Please enter your email address below. We'll send you a code to access all your games.</p>

<label for='email'>Email:</label>
<Input type='email' id='email' autoComplete='email' placeholder='[email protected]' bind={auth.email} />
<Input onChange={() => undefined} value={auth.email.value} type='email' id='email' autoComplete='email' placeholder='[email protected]' bind={auth.email} />
{auth.state.value === 'EMAIL_INCORRECT' && <p class={styles.error}>Failed sending login code. Did you enter the right email?</p>}

<Button class={styles.submit} icon={IoPaperPlaneOutline} iconSide='right' accent type='submit' disabled={!auth.emailValid.value} loading={auth.isLoading.value}>
Send code
</Button>
Expand All @@ -54,9 +54,9 @@ export default function Login({ session, email, to }: LoginProps) {
</LinkButton>
</span>
</p>

<label for='code'>Code:</label>
<Input id='code' type='text' maxLength={6} placeholder='123456' bind={auth.code} />
<Input onChange={() => undefined} value={auth.code.value} id='code' type='text' maxLength={6} placeholder='123456' bind={auth.code} />
{auth.state.value === 'CODE_INCORRECT' && <p class={styles.error}>Incorrect login code.</p>}

<Button class={styles.submit} accent type='submit' disabled={!auth.codeValid.value} loading={auth.isLoading.value}>
Expand All @@ -67,4 +67,4 @@ export default function Login({ session, email, to }: LoginProps) {
</div>
</div>
)
}
}
6 changes: 3 additions & 3 deletions src/components/big-interactive-pages/migrate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ export default function Migrate({ session, intitialEmail }: MigrateProps) {
.map((game) => ({ id: gameIds[game.name], legacy: game }))

localStorage.setItem('seenMigration', 'true')

if (session?.session.full) {
window.location.replace('/~')
} else {
Expand All @@ -177,7 +177,7 @@ export default function Migrate({ session, intitialEmail }: MigrateProps) {
{session?.session.full ? null : (
<div class={styles.emailEntry}>
<label for='email'>Enter your email:</label>
<Input type='email' autoComplete='email' id='email' placeholder={'[email protected]'} bind={email} />
<Input onChange={() => undefined} value={email.value} type='email' autoComplete='email' id='email' placeholder={'[email protected]'} bind={email} />
</div>
)}

Expand All @@ -195,4 +195,4 @@ export default function Migrate({ session, intitialEmail }: MigrateProps) {
</div>
</div>
)
}
}
2 changes: 1 addition & 1 deletion src/components/navbar-editor.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ const prettifyCode = () => {
// Set the options for js_beautify
const options = {
indent_size: 2, // Indent by 2 spaces
brace_style: "collapse,preserve-inline", // Collapse braces and preserve inline
brace_style: "collapse,preserve-inline" as any, // Collapse braces and preserve inline
};

const { js_beautify } = beautifier;
Expand Down
2 changes: 1 addition & 1 deletion src/components/navbar-main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { IoAdd, IoLogoGithub, IoOpenOutline } from "react-icons/io5";
import Button from "./design-system/button";
import styles from "./navbar.module.css";
import { SessionInfo } from "../lib/game-saving/account";
import AnnouncementBanner from "./popups-etc/announcement-banner";
// import AnnouncementBanner from "./popups-etc/announcement-banner";
interface MainNavbarProps {
session: SessionInfo | null;
transparent?: boolean;
Expand Down
2 changes: 1 addition & 1 deletion src/components/popups-etc/chat-component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Answer the questions that follow based on this unless new code is provided.`;
} catch (err) {
loading.value = false;
// info.value = "An error occurred...";
info.value = err.message;
info.value = (err as Error).message;
}
};

Expand Down
6 changes: 3 additions & 3 deletions src/components/popups-etc/draft-warning.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function DraftWarningModal(props: DraftWarningModalProps) {
if (auth.state.value === 'EMAIL_INCORRECT') persist(props.persistenceState, auth.email.value)
}} class={styles.stack}>
<div class={styles.inputRow}>
<Input type='email' autoComplete='email' placeholder='[email protected]' bind={auth.email} />
<Input onChange={() => undefined} value={auth.email.value} type='email' autoComplete='email' placeholder='[email protected]' bind={auth.email} />
<Button accent type='submit' disabled={!auth.emailValid.value} loading={auth.isLoading.value}>
Start coding
</Button>
Expand Down Expand Up @@ -70,7 +70,7 @@ export default function DraftWarningModal(props: DraftWarningModalProps) {
<p>You've used Sprig before, so we emailed you a code to log in and access all your games. Enter login code:</p>

<div class={`${styles.inputRow} ${styles.limited}`}>
<Input maxLength={6} class={styles.center} type='text' bind={auth.code} placeholder='123456' />
<Input onChange={() => undefined} value={auth.code.value} maxLength={6} class={styles.center} type='text' bind={auth.code} placeholder='123456' />
<Button accent type='submit' disabled={!auth.codeValid.value} loading={auth.isLoading.value}>
Log in
</Button>
Expand All @@ -88,4 +88,4 @@ export default function DraftWarningModal(props: DraftWarningModalProps) {
</div>
</div>
)
}
}
8 changes: 4 additions & 4 deletions src/components/popups-etc/save-prompt.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ interface SavePromptProps {
persistenceState: Signal<PersistenceState>
onClose: () => void
}

export default function SavePrompt(props: SavePromptProps) {
const email = useSignal(props.persistenceState.value.session?.user.email ?? '')
const emailValid = useComputed(() => isValidEmail(email.value))
Expand All @@ -38,7 +38,7 @@ export default function SavePrompt(props: SavePromptProps) {
}}>
<p>Enter your email to save your work, we'll send you a link for later:</p>
<div class={popupStyles.inputRow}>
<Input type='email' autoComplete='email' placeholder='[email protected]' bind={email} />
<Input onChange={() => undefined} value={email.value} type='email' autoComplete='email' placeholder='[email protected]' bind={email} />
<Button accent type='submit' disabled={!emailValid.value}>
Save
</Button>
Expand All @@ -54,10 +54,10 @@ export default function SavePrompt(props: SavePromptProps) {
<Button accent onClick={() => props.onClose()}>Done</Button>
</>)
}

return (
<div class={popupStyles.popup}>
{content}
</div>
)
}
}
4 changes: 2 additions & 2 deletions src/integrations/generate-metadata.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Astro integration that generatest the game/metadata.json
*
*
* How it works:
* 1. It walks/scans the ./games/ directory
* 2. It searches each file for metadata, if anything isn't found it halts the build/dev
Expand All @@ -26,7 +26,7 @@ const regexExpr = {
*
* TODO!
*/
const isMetadataValid = (meta: any): boolean => {
const isMetadataValid = (_: any): boolean => {
return true;
};

Expand Down
18 changes: 9 additions & 9 deletions src/lib/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -134,23 +134,23 @@ export const themes: Partial<Record<ThemeType, Theme>> = {

export const switchTheme = (themeType: ThemeType) => {
theme.value = themeType;

// store the new theme value in local storage
localStorage.setItem("theme", themeType);

const themeValue = themes[themeType];
// set the document values
const documentStyle = document.body.style;
documentStyle.background = themeValue.background;
document.documentElement.style.setProperty(`--accent`, themeValue.accent);
document.documentElement.style.setProperty(`--accent-dark`, themeValue.accentDark);
document.documentElement.style.setProperty(`--fg-muted-on-accent`, themeValue.fgMutedOnAccent);
documentStyle.color = themeValue.color;
documentStyle.background = themeValue!.background;
document.documentElement.style.setProperty(`--accent`, themeValue!.accent);
document.documentElement.style.setProperty(`--accent-dark`, themeValue!.accentDark);
document.documentElement.style.setProperty(`--fg-muted-on-accent`, themeValue!.fgMutedOnAccent);
documentStyle.color = themeValue!.color;

// change the color of the text in elements having .copy-container style
// These includes pages such as 'Gallery' and 'Your Games'
const copyContainer = document.querySelector(".copy-container") as HTMLDivElement;
if (copyContainer) {
copyContainer.style.color = themeValue.copyContainerText;
copyContainer.style.color = themeValue!.copyContainerText;
}
}
}
Loading