Skip to content
Merged
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
26 changes: 26 additions & 0 deletions .github/workflows/prettier-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
name: Prettier Check
on:
push:
branches: [master]
pull_request:

jobs:
prettier:
name: "Checking code style"
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 20.x

- name: Enable Corepack
run: corepack enable

- name: Install dependencies
run: yarn install --immutable

- name: Run Prettier check
run: yarn run prettier:check
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.env
.idea
.DS_Store
node_modules
.yarn
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.idea
.yarn
deno.lock
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
nodeLinker: node-modules
23 changes: 13 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,23 @@

Run all OpenHotel stack locally with Docker.

| Service | Repo | URL |
| ------- | ------------------- | --------------------- |
| client | `openhotel/openhotel` | http://localhost:1994 |
| auth | `openhotel/auth` | http://localhost:2024 |
| web | `openhotel/web` | http://localhost:2025 |
| onet | `openhotel/onet` | http://localhost:9400 |
| Service | Repo | URL |
| ------------ | ------------------------ | --------------------- |
| client | `openhotel/openhotel` | http://localhost:1994 |
| auth | `openhotel/auth` | http://localhost:2024 |
| web | `openhotel/web` | http://localhost:2025 |
| onet | `openhotel/onet` | http://localhost:9400 |
| asset-editor | `openhotel/asset-editor` | http://localhost:2030 |
| static | `openhotel/static` | http://localhost:1995 |
| s3 | SeaweedFS | http://localhost:9000 |
| static | `openhotel/static` | http://localhost:1995 |
| s3 | SeaweedFS | http://localhost:9000 |

## Requirements

- Docker
- The service repos cloned next to this one (or set `REPOS_DIR` in `.env`)
- Deno
- Git

The service repos are cloned next to this one (or in `REPOS_DIR` from `.env`):

```
openhotel/
Expand All @@ -31,7 +34,7 @@ openhotel/
## Usage

```bash
cp .env.example .env
deno task setup # clone missing repos and create dev configs
deno task up # everything (in background)
deno task up auth client # some services
deno task logs # logs of all services
Expand Down
1 change: 0 additions & 1 deletion compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ services:
- /src/onet/node_modules
- deno-cache:/root/.cache/deno


web:
<<: *dev
container_name: web
Expand Down
3 changes: 3 additions & 0 deletions configs/asset-editor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
version: development
auth:
url: http://localhost:2024
1 change: 1 addition & 0 deletions configs/auth.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version: development
7 changes: 7 additions & 0 deletions configs/client.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
version: development
auth:
api: http://localhost:2024
onet:
api: http://localhost:9400
phantom:
enabled: false
2 changes: 2 additions & 0 deletions configs/onet.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
auth:
api: http://localhost:2024/api/v3
1 change: 1 addition & 0 deletions configs/static.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version: development
1 change: 1 addition & 0 deletions configs/web.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
version: development
7 changes: 7 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
{
"tasks": {
"setup": "deno run --allow-read --allow-write --allow-run=git,docker setup.ts",
"up": "docker compose up -d --build",
"logs": "docker compose logs -f --tail=100",
"down": "docker compose down"
},
"imports": {
"@std/dotenv": "jsr:@std/dotenv@0.225.8",
"@std/fs": "jsr:@std/fs@1.0.24",
"@std/path": "jsr:@std/path@1.1.6",
"@std/yaml": "jsr:@std/yaml@1.3.0"
}
}
48 changes: 48 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"scripts": {
"prettier:check": "prettier -c ./",
"prettier:write": "prettier --write ."
},
"devDependencies": {
"prettier": "3.9.5"
},
"packageManager": "yarn@4.6.0"
}
181 changes: 181 additions & 0 deletions setup.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
import { parse as parseEnv } from "@std/dotenv";
import { parse as parseYaml } from "@std/yaml";
import { exists } from "@std/fs";
import { dirname, join, resolve } from "@std/path";

type Service = {
name: string;
repo: string;
config: string;
};

const SERVICES: Service[] = [
{
name: "client",
repo: "openhotel",
config: "app/server/config.yml",
},
{
name: "auth",
repo: "auth",
config: "app/server/config.yml",
},
{
name: "onet",
repo: "onet",
config: "config.yml",
},
{
name: "web",
repo: "web",
config: "app/server/config.yml",
},
{
name: "asset-editor",
repo: "asset-editor",
config: "app/server/config.yml",
},
{
name: "static",
repo: "static",
config: "app/server/config.yml",
},
];

const ROOT = import.meta.dirname!;

const ok = (message: string) => console.log(`%c✔ ${message}`, "color: green");
const warn = (message: string) =>
console.log(`%c⚠ ${message}`, "color: yellow");
const fail = (message: string) => {
console.log(`%c✘ ${message}`, "color: red");
Deno.exit(1);
};

const run = async (cmd: string, ...args: string[]): Promise<boolean> => {
try {
const { success } = await new Deno.Command(cmd, {
args,
stdout: "null",
stderr: "inherit",
}).output();

return success;
} catch {
return false;
}
};

const checkRequirements = async () => {
if (!(await run("git", "--version"))) fail("git not found");
if (!(await run("docker", "compose", "version"))) {
warn("docker compose not found, you will need it to run the stack");
}
};

const loadEnv = async (): Promise<Record<string, string>> => {
const envPath = join(ROOT, ".env");

if (!(await exists(envPath))) {
await Deno.copyFile(join(ROOT, ".env.example"), envPath);
ok(".env created from .env.example");
}

return parseEnv(await Deno.readTextFile(envPath));
};

const cloneRepos = async (reposDir: string) => {
for (const { repo } of SERVICES) {
const repoPath = join(reposDir, repo);

if (await exists(repoPath)) {
ok(`${repo} already exists`);
continue;
}

console.log(`Cloning ${repo}...`);
const cloned = await run(
"git",
"clone",
`https://github.com/openhotel/${repo}.git`,
repoPath,
);
if (cloned) ok(`${repo} cloned`);
else warn(`${repo} could not be cloned!`);
}
};

const readYaml = async (path: string): Promise<Record<string, unknown>> =>
parseYaml(await Deno.readTextFile(path)) ?? {};

const flatten = (
object: Record<string, unknown>,
prefix = "",
): Record<string, unknown> =>
Object.entries(object).reduce((flat, [key, value]) => {
const path = prefix ? `${prefix}.${key}` : key;

return typeof value === "object" && value !== null && !Array.isArray(value)
? { ...flat, ...flatten(value, path) }
: { ...flat, [path]: value };
}, {});

const checkConfig = async (
service: Service,
configPath: string,
templatePath: string,
) => {
let config: Record<string, unknown>;
try {
config = flatten(await readYaml(configPath));
} catch {
warn(`${service.name}: ${configPath} is not valid yaml`);
return;
}

const template = flatten(await readYaml(templatePath));
for (const [key, value] of Object.entries(template)) {
if (config[key] !== value) {
warn(
`${service.name}: '${key}' should be '${value}' (is '${config[key]}')`,
);
}
}
};

const copyConfigs = async (reposDir: string) => {
for (const service of SERVICES) {
const repoPath = join(reposDir, service.repo);
if (!(await exists(repoPath))) continue;

const configPath = join(repoPath, service.config);
const templatePath = join(ROOT, "configs", `${service.name}.yml`);

if (await exists(configPath)) {
await checkConfig(service, configPath, templatePath);
continue;
}

await Deno.mkdir(dirname(configPath), { recursive: true });
await Deno.copyFile(templatePath, configPath);

ok(`${service.name}: config created`);
}
};

await checkRequirements();
const env = await loadEnv();
const reposDir = resolve(ROOT, env.REPOS_DIR ?? "..");

await cloneRepos(reposDir);
await copyConfigs(reposDir);

console.log(`
Ready! Next steps:
1. deno task up auth
2. Sign up at http://localhost:2024 and create a hotel
3. Fill the tokens:
- openhotel/app/server/config.yml → auth.enabled: true, auth.licenseToken
- onet/config.yml → auth.token
4. deno task up
`);
23 changes: 23 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# This file is generated by running "yarn install" inside your project.
# Manual changes might be lost - proceed with caution!

__metadata:
version: 8
cacheKey: 10c0

"prettier@npm:3.9.5":
version: 3.9.5
resolution: "prettier@npm:3.9.5"
bin:
prettier: bin/prettier.cjs
checksum: 10c0/0349dd9e6d8010965de6f69e6b6ee2484b8caf78c66675afced6c75ad60ff24c3a2a4f41153fb8adeaee4d8f539641b48cebc71d283cec4d146e9962126c5ceb
languageName: node
linkType: hard

"root-workspace-0b6124@workspace:.":
version: 0.0.0-use.local
resolution: "root-workspace-0b6124@workspace:."
dependencies:
prettier: "npm:3.9.5"
languageName: unknown
linkType: soft
Loading