Skip to content

Commit

Permalink
deploy
Browse files Browse the repository at this point in the history
  • Loading branch information
cobbinma committed Sep 24, 2023
1 parent c04e2b7 commit fb939cb
Show file tree
Hide file tree
Showing 12 changed files with 218 additions and 103 deletions.
47 changes: 47 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# flyctl launch added from .gitignore
**/.vscode

# flyctl launch added from conjugation-api/.gitignore
# Generated by Cargo
# will have compiled files and executables
conjugation-api/**/debug
conjugation-api/**/target
conjugation-api/**/.idea

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
conjugation-api/**/Cargo.lock

# These are backup files generated by rustfmt
conjugation-api/**/**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
conjugation-api/**/*.pdb

# flyctl launch added from conjugation-api/.idea/.gitignore
# Default ignored files
conjugation-api/.idea/shelf
conjugation-api/.idea/workspace.xml
# Editor-based HTTP Client requests
conjugation-api/.idea/httpRequests
# Datasource local storage ignored files
conjugation-api/.idea/dataSources
conjugation-api/.idea/dataSources.local.xml

# flyctl launch added from conjugation-ui/.gitignore
conjugation-ui/**/.DS_Store
conjugation-ui/**/node_modules
conjugation-ui/build
conjugation-ui/.svelte-kit
conjugation-ui/package
conjugation-ui/**/.env
conjugation-ui/**/.env.*
!conjugation-ui/**/.env.example
conjugation-ui/**/.vercel
conjugation-ui/**/.output
conjugation-ui/**/vite.config.js.timestamp-*
conjugation-ui/**/vite.config.ts.timestamp-*

# flyctl launch added from conjugation-ui/node_modules/tailwindcss/stubs/.gitignore
!conjugation-ui/node_modules/tailwindcss/stubs/**/*
fly.toml
70 changes: 70 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Stage 1: Build the Rust API
FROM rust:latest AS rust_builder

# Create a work directory for the Rust API
WORKDIR /app/api

# Copy the Rust API source code into the container
COPY conjugation-api/ .

# Build the Rust API
RUN cargo build --release

# Stage 2: Build the Bun UI
FROM node:latest AS ui_builder

RUN npm install -g bun

# Create a work directory for the Bun UI
WORKDIR /app/ui

# Copy the Bun UI source code into the container
COPY conjugation-ui/ .

# Install dependencies and build the Bun UI
RUN bun install
RUN bun run build

# Stage 3: Final Image
FROM debian:latest

# Install Supervisor
RUN apt-get update && apt-get install -y supervisor nodejs

# Create a work directory for the final application
WORKDIR /app

# Copy the built Rust API from the Rust builder stage
COPY --from=rust_builder /app/api/target/release/conjugation-api ./app/api/
COPY --from=rust_builder /app/api/data ./data

# Copy the built Bun UI from the UI builder stage
COPY --from=ui_builder /app/ui/build ./ui/build
COPY --from=ui_builder /app/ui/package.json ./ui/package.json
COPY --from=ui_builder /app/ui/node_modules ./ui/node_modules

RUN echo "[supervisord]" >> /etc/supervisor/conf.d/app.conf
RUN echo "logfile=/dev/stdout" >> /etc/supervisor/conf.d/app.conf
RUN echo "logfile_maxbytes=0" >> /etc/supervisor/conf.d/app.conf
RUN echo "loglevel=info" >> /etc/supervisor/conf.d/app.conf
RUN echo "pidfile=/tmp/supervisord.pid" >> /etc/supervisor/conf.d/app.conf
RUN echo "nodaemon=true" >> /etc/supervisor/conf.d/app.conf
RUN echo "user=root" >> /etc/supervisor/conf.d/app.conf

RUN echo "[unix_http_server]" >> /etc/supervisor/conf.d/app.conf
RUN echo "file=/tmp/supervisor.sock" >> /etc/supervisor/conf.d/app.conf

# Create a Supervisor configuration file to run both processes
RUN echo "[program:api]" >> /etc/supervisor/conf.d/app.conf
RUN echo "command=./app/api/conjugation-api" >> /etc/supervisor/conf.d/app.conf
RUN echo "autostart=true" >> /etc/supervisor/conf.d/app.conf
RUN echo "[program:ui]" >> /etc/supervisor/conf.d/app.conf
RUN echo "command=node ./ui/build/" >> /etc/supervisor/conf.d/app.conf
RUN echo "autostart=true" >> /etc/supervisor/conf.d/app.conf

# Expose ports if needed (adjust as per your requirements)
EXPOSE 8080
EXPOSE 3000

# Start Supervisor to manage both processes
CMD ["supervisord", "-c", "/etc/supervisor/supervisord.conf"]
17 changes: 1 addition & 16 deletions conjugation-api/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -199,24 +199,9 @@ async fn handle_graphiql(_: Request<State>) -> tide::Result<impl Into<Response>>
async fn main() -> std::io::Result<()> {
let db = SqlitePool::connect(DB_URL).await.unwrap();
let mut app = Server::with_state(State { pool: db });
app.with(
tide::security::CorsMiddleware::new()
.allow_methods(
"GET, PUT, POST, DELETE, HEAD, OPTIONS"
.parse::<http_types::headers::HeaderValue>()
.unwrap(),
)
.allow_origin(tide::security::Origin::from("http://localhost:5173"))
.allow_headers(
"Authorization, Accept, Content-Type"
.parse::<http_types::headers::HeaderValue>()
.unwrap(),
)
.allow_credentials(true),
);
app.at("/").get(Redirect::permanent("/graphiql"));
app.at("/graphql").post(handle_graphql);
app.at("/graphiql").get(handle_graphiql);
app.listen("0.0.0.0:8080").await?;
app.listen("[::]:8080").await?;
Ok(())
}
Binary file modified conjugation-ui/bun.lockb
Binary file not shown.
4 changes: 4 additions & 0 deletions conjugation-ui/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"name": "conjugation-ui",
"version": "0.0.1",
"proxy": "http://localhost:8080",
"scripts": {
"dev": "vite dev",
"build": "vite build",
Expand All @@ -12,11 +13,13 @@
"codegen": "graphql-codegen --config codegen.ts"
},
"devDependencies": {
"@flydotio/dockerfile": "latest",
"@fontsource/fira-mono": "^4.5.10",
"@graphql-codegen/cli": "5.0.0",
"@graphql-codegen/typescript": "4.0.1",
"@neoconfetti/svelte": "^1.0.0",
"@sveltejs/adapter-auto": "^2.0.0",
"@sveltejs/adapter-node": "^1.3.1",
"@sveltejs/kit": "^1.20.4",
"@tailwindcss/typography": "^0.5.10",
"@types/cookie": "^0.5.1",
Expand All @@ -41,6 +44,7 @@
"type": "module",
"dependencies": {
"@graphql-typed-document-node/core": "^3.2.0",
"axios": "^1.5.0",
"graphql": "^16.8.1",
"svelte-apollo": "^0.5.0"
}
Expand Down
93 changes: 28 additions & 65 deletions conjugation-ui/src/components/Verb.svelte
Original file line number Diff line number Diff line change
@@ -1,79 +1,42 @@
<script lang="ts">
import { onMount } from 'svelte';
import { query } from 'svelte-apollo';
import { gql } from '@apollo/client/core';
import type { Tense, QueryRootConjugatedVerbArgs, QueryRoot } from '../generated/graphql';
import type { ConjugatedVerb } from '../generated/graphql';
import Game from './Game.svelte';
import Table from './Table.svelte';
import Error from './Error.svelte';
export let infinitive: string;
export let tense: Tense;
export let verb: ConjugatedVerb;
let playing: boolean;
let played: boolean;
const VERB_QUERY = gql`
query GetVerb($infinitive: String!, $tense: Tense!) {
conjugatedVerb(infinitive: $infinitive, tense: $tense) {
tense
infinitive
verbEnglish
yo
tu
el
nosotros
vosotros
ellos
}
}
`;
const verb = query<QueryRoot, QueryRootConjugatedVerbArgs>(VERB_QUERY, {
variables: { infinitive, tense }
});
let playing: boolean;
</script>

{#await $verb}
<span class="loading loading-spinner loading-lg" />
{:then result}
{#if result.data?.conjugatedVerb}
<div class="text-column">
<h1>{result.data.conjugatedVerb.infinitive}</h1>
<div class="text-column">
<h1>{verb.infinitive}</h1>

<h2>{result.data.conjugatedVerb.tense.toLowerCase()}</h2>
<h2>{verb.tense.toLowerCase()}</h2>

<p>
{result.data.conjugatedVerb.verbEnglish}
</p>
<p>
{verb.verbEnglish}
</p>

{#if played && !playing}
<Table verb={result.data.conjugatedVerb} />
{/if}
{#if played && !playing}
<Table {verb} />
{/if}

{#if !playing}
<button class="btn modal-button btn-secondary" on:click={() => (playing = true)}
>Practise</button
>
{:else}
<div class="modal" class:modal-open={playing}>
<div class="modal-box">
<Game
verb={result.data.conjugatedVerb}
close={() => {
playing = false;
played = true;
}}
/>
</div>
</div>
{/if}
{#if !playing}
<button class="btn modal-button btn-secondary" on:click={() => (playing = true)}
>Practise</button
>
{:else}
<div class="modal" class:modal-open={playing}>
<div class="modal-box">
<Game
{verb}
close={() => {
playing = false;
played = true;
}}
/>
</div>
</div>
{:else if result.loading}
<span class="loading loading-spinner loading-lg" />
{:else if result.error}
<Error />
{/if}
{:catch}
<Error />
{/await}
</div>
4 changes: 1 addition & 3 deletions conjugation-ui/src/routes/+page.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1 @@
// since there's no dynamic data here, we can prerender
// it so that it gets served as a static asset in production
export const prerender = true;

Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Tense, type QueryRootConjugatedVerbArgs } from '../../../../generated/graphql';
import axios from 'axios';

/** @type {import('./$types').PageServerLoad} */
export async function load({ params }) {
const tense = Tense[params.tense as keyof typeof Tense];

try {
const variables: QueryRootConjugatedVerbArgs = {
infinitive: params.infinitive,
tense
};

const response = await axios.post('http://api.process.spanish.internal:8080/graphql', {
query: `
query GetVerb($infinitive: String!, $tense: Tense!) {
conjugatedVerb(infinitive: $infinitive, tense: $tense) {
tense
infinitive
verbEnglish
yo
tu
el
nosotros
vosotros
ellos
}
}
`,
variables
});

return response.data.data.conjugatedVerb;
} catch (error) {
console.error(`Error in load function for /: ${error}`);
}
}
16 changes: 4 additions & 12 deletions conjugation-ui/src/routes/verb/[infinitive]/[tense]/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
<script lang="ts">
import { ApolloClient, InMemoryCache } from '@apollo/client/core';
import { setClient } from 'svelte-apollo';
import Verb from '../../../../components/Verb.svelte';
import { page } from '$app/stores';
import { Tense } from '../../../../generated/graphql';
import type { ConjugatedVerb } from '../../../../generated/graphql';
const client = new ApolloClient({
uri: 'http://localhost:8080/graphql',
cache: new InMemoryCache()
});
setClient(client);
const tense = Tense[$page.data.tense as keyof typeof Tense];
/** @type {import('./$types').PageData} */
export let data: ConjugatedVerb;
</script>

<svelte:head>
Expand All @@ -20,5 +12,5 @@
</svelte:head>

<div class="prose h-2/3">
<Verb infinitive={$page.data.infinitive} {tense} />
<Verb verb={data} />
</div>
7 changes: 1 addition & 6 deletions conjugation-ui/src/routes/verb/[infinitive]/[tense]/+page.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1 @@
export const load = ({ params }) => {
return {
infinitive: params.infinitive,
tense: params.tense
};
};

2 changes: 1 addition & 1 deletion conjugation-ui/svelte.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import adapter from '@sveltejs/adapter-auto';
import adapter from '@sveltejs/adapter-node';
import { vitePreprocess } from '@sveltejs/kit/vite';

/** @type {import('@sveltejs/kit').Config} */
Expand Down
24 changes: 24 additions & 0 deletions fly.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# fly.toml app configuration file generated for spanish on 2023-09-24T14:52:31+01:00
#
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
#

app = "spanish"
primary_region = "lhr"

[processes]
api = "./app/api/conjugation-api"
ui = "node ./ui/build/"

[[services]]
processes = ["api"]
protocol = "tcp"
internal_port = 8080

[http_service]
internal_port = 3000
force_https = true
auto_stop_machines = true
auto_start_machines = true
min_machines_running = 0
processes = ["ui"]

0 comments on commit fb939cb

Please sign in to comment.