mirror of
https://github.com/kou029w/quot.git
synced 2025-01-18 16:08:03 +00:00
create quot project
This commit is contained in:
parent
8d76de4274
commit
ac30da6b61
20 changed files with 594 additions and 0 deletions
1
README.md
Normal file
1
README.md
Normal file
|
@ -0,0 +1 @@
|
|||
# Quot
|
1
app/.dockerignore
Symbolic link
1
app/.dockerignore
Symbolic link
|
@ -0,0 +1 @@
|
|||
.gitignore
|
2
app/.gitignore
vendored
Normal file
2
app/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.env
|
||||
node_modules
|
5
app/Dockerfile
Normal file
5
app/Dockerfile
Normal file
|
@ -0,0 +1,5 @@
|
|||
FROM node:18.7.0-alpine
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
RUN npm ci --production
|
||||
CMD ["npm", "start"]
|
10
app/compose.yml
Normal file
10
app/compose.yml
Normal file
|
@ -0,0 +1,10 @@
|
|||
services:
|
||||
app:
|
||||
image: kou029w/quot-app
|
||||
build: "."
|
||||
restart: unless-stopped
|
||||
init: true
|
||||
user: ${UID:-1000}:${GID:-1000}
|
||||
ports: ["8080:8080"]
|
||||
volumes:
|
||||
- ".:/app"
|
189
app/package-lock.json
generated
Normal file
189
app/package-lock.json
generated
Normal file
|
@ -0,0 +1,189 @@
|
|||
{
|
||||
"name": "@quot/app",
|
||||
"version": "0.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "@quot/app",
|
||||
"version": "0.0.0",
|
||||
"dependencies": {
|
||||
"@exampledev/new.css": "^1.1.3",
|
||||
"esbuild": "^0.15.5",
|
||||
"esbuild-register": "^3.3.3",
|
||||
"solid-js": "^1.4.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node18-strictest-esm": "^1.0.0",
|
||||
"@types/node": "^18.7.8",
|
||||
"typescript": "^4.7.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.7.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@exampledev/new.css": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@exampledev/new.css/-/new.css-1.1.3.tgz",
|
||||
"integrity": "sha512-qhbGfqBRwUlM6MCSaJdUfjq86opNCMvM+6kVvs6S0kYhy0V8dKbe4rDMIklEJGuMc5QH5OuPjdCReu9I0tim2w=="
|
||||
},
|
||||
"node_modules/@tsconfig/node18-strictest-esm": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node18-strictest-esm/-/node18-strictest-esm-1.0.0.tgz",
|
||||
"integrity": "sha512-4lY2mZXGFaW13OYcz6kwWFussLbIAg5XBlS2h72jzr4mqr/CuFmF04S7hkpBYbw0k/TNQ4tFLx1/j6VpBqr3Tg==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "18.7.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.8.tgz",
|
||||
"integrity": "sha512-/YP55EMK2341JkODUb8DM9O0x1SIz2aBvyF33Uf1c76St3VpsMXEIW0nxuKkq/5cxnbz0RD9cfwNZHEAZQD3ag==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.15.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.5.tgz",
|
||||
"integrity": "sha512-VSf6S1QVqvxfIsSKb3UKr3VhUCis7wgDbtF4Vd9z84UJr05/Sp2fRKmzC+CSPG/dNAPPJZ0BTBLTT1Fhd6N9Gg==",
|
||||
"hasInstallScript": true,
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/linux-loong64": "0.15.5",
|
||||
"esbuild-android-64": "0.15.5",
|
||||
"esbuild-android-arm64": "0.15.5",
|
||||
"esbuild-darwin-64": "0.15.5",
|
||||
"esbuild-darwin-arm64": "0.15.5",
|
||||
"esbuild-freebsd-64": "0.15.5",
|
||||
"esbuild-freebsd-arm64": "0.15.5",
|
||||
"esbuild-linux-32": "0.15.5",
|
||||
"esbuild-linux-64": "0.15.5",
|
||||
"esbuild-linux-arm": "0.15.5",
|
||||
"esbuild-linux-arm64": "0.15.5",
|
||||
"esbuild-linux-mips64le": "0.15.5",
|
||||
"esbuild-linux-ppc64le": "0.15.5",
|
||||
"esbuild-linux-riscv64": "0.15.5",
|
||||
"esbuild-linux-s390x": "0.15.5",
|
||||
"esbuild-netbsd-64": "0.15.5",
|
||||
"esbuild-openbsd-64": "0.15.5",
|
||||
"esbuild-sunos-64": "0.15.5",
|
||||
"esbuild-windows-32": "0.15.5",
|
||||
"esbuild-windows-64": "0.15.5",
|
||||
"esbuild-windows-arm64": "0.15.5"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-linux-64": {
|
||||
"version": "0.15.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.5.tgz",
|
||||
"integrity": "sha512-ne0GFdNLsm4veXbTnYAWjbx3shpNKZJUd6XpNbKNUZaNllDZfYQt0/zRqOg0sc7O8GQ+PjSMv9IpIEULXVTVmg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild-register": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.3.tgz",
|
||||
"integrity": "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==",
|
||||
"peerDependencies": {
|
||||
"esbuild": ">=0.12 <1"
|
||||
}
|
||||
},
|
||||
"node_modules/solid-js": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.4.8.tgz",
|
||||
"integrity": "sha512-XErZdnnYYXF7OwGSUAPcua2y5/ELB/c53zFCpWiEGqxTNoH1iQghzI8EsHJXk06sNn+Z/TGhb8bPDNNGSgimag=="
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"dev": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4.2.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@exampledev/new.css": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@exampledev/new.css/-/new.css-1.1.3.tgz",
|
||||
"integrity": "sha512-qhbGfqBRwUlM6MCSaJdUfjq86opNCMvM+6kVvs6S0kYhy0V8dKbe4rDMIklEJGuMc5QH5OuPjdCReu9I0tim2w=="
|
||||
},
|
||||
"@tsconfig/node18-strictest-esm": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@tsconfig/node18-strictest-esm/-/node18-strictest-esm-1.0.0.tgz",
|
||||
"integrity": "sha512-4lY2mZXGFaW13OYcz6kwWFussLbIAg5XBlS2h72jzr4mqr/CuFmF04S7hkpBYbw0k/TNQ4tFLx1/j6VpBqr3Tg==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "18.7.8",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.7.8.tgz",
|
||||
"integrity": "sha512-/YP55EMK2341JkODUb8DM9O0x1SIz2aBvyF33Uf1c76St3VpsMXEIW0nxuKkq/5cxnbz0RD9cfwNZHEAZQD3ag==",
|
||||
"dev": true
|
||||
},
|
||||
"esbuild": {
|
||||
"version": "0.15.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.15.5.tgz",
|
||||
"integrity": "sha512-VSf6S1QVqvxfIsSKb3UKr3VhUCis7wgDbtF4Vd9z84UJr05/Sp2fRKmzC+CSPG/dNAPPJZ0BTBLTT1Fhd6N9Gg==",
|
||||
"requires": {
|
||||
"@esbuild/linux-loong64": "0.15.5",
|
||||
"esbuild-android-64": "0.15.5",
|
||||
"esbuild-android-arm64": "0.15.5",
|
||||
"esbuild-darwin-64": "0.15.5",
|
||||
"esbuild-darwin-arm64": "0.15.5",
|
||||
"esbuild-freebsd-64": "0.15.5",
|
||||
"esbuild-freebsd-arm64": "0.15.5",
|
||||
"esbuild-linux-32": "0.15.5",
|
||||
"esbuild-linux-64": "0.15.5",
|
||||
"esbuild-linux-arm": "0.15.5",
|
||||
"esbuild-linux-arm64": "0.15.5",
|
||||
"esbuild-linux-mips64le": "0.15.5",
|
||||
"esbuild-linux-ppc64le": "0.15.5",
|
||||
"esbuild-linux-riscv64": "0.15.5",
|
||||
"esbuild-linux-s390x": "0.15.5",
|
||||
"esbuild-netbsd-64": "0.15.5",
|
||||
"esbuild-openbsd-64": "0.15.5",
|
||||
"esbuild-sunos-64": "0.15.5",
|
||||
"esbuild-windows-32": "0.15.5",
|
||||
"esbuild-windows-64": "0.15.5",
|
||||
"esbuild-windows-arm64": "0.15.5"
|
||||
}
|
||||
},
|
||||
"esbuild-linux-64": {
|
||||
"version": "0.15.5",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-linux-64/-/esbuild-linux-64-0.15.5.tgz",
|
||||
"integrity": "sha512-ne0GFdNLsm4veXbTnYAWjbx3shpNKZJUd6XpNbKNUZaNllDZfYQt0/zRqOg0sc7O8GQ+PjSMv9IpIEULXVTVmg==",
|
||||
"optional": true
|
||||
},
|
||||
"esbuild-register": {
|
||||
"version": "3.3.3",
|
||||
"resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.3.3.tgz",
|
||||
"integrity": "sha512-eFHOkutgIMJY5gc8LUp/7c+LLlDqzNi9T6AwCZ2WKKl3HmT+5ef3ZRyPPxDOynInML0fgaC50yszPKfPnjC0NQ==",
|
||||
"requires": {}
|
||||
},
|
||||
"solid-js": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/solid-js/-/solid-js-1.4.8.tgz",
|
||||
"integrity": "sha512-XErZdnnYYXF7OwGSUAPcua2y5/ELB/c53zFCpWiEGqxTNoH1iQghzI8EsHJXk06sNn+Z/TGhb8bPDNNGSgimag=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "4.7.4",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz",
|
||||
"integrity": "sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
24
app/package.json
Normal file
24
app/package.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "@quot/app",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "tsc --noEmit",
|
||||
"start": "node -r esbuild-register src/server.ts"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^18.7.0"
|
||||
},
|
||||
"packageManager": "npm@8.15.0",
|
||||
"dependencies": {
|
||||
"@exampledev/new.css": "^1.1.3",
|
||||
"esbuild": "^0.15.5",
|
||||
"esbuild-register": "^3.3.3",
|
||||
"solid-js": "^1.4.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node18-strictest-esm": "^1.0.0",
|
||||
"@types/node": "^18.7.8",
|
||||
"typescript": "^4.7.4"
|
||||
}
|
||||
}
|
38
app/src/app.tsx
Normal file
38
app/src/app.tsx
Normal file
|
@ -0,0 +1,38 @@
|
|||
import { createSignal } from "solid-js";
|
||||
import Index from "./pages/index";
|
||||
import Page from "./pages/page";
|
||||
|
||||
const routes = {
|
||||
"/": Index,
|
||||
};
|
||||
|
||||
export default () => {
|
||||
const [pathname, setPathname] = createSignal(
|
||||
document.location.pathname as keyof typeof routes
|
||||
);
|
||||
|
||||
document.body.addEventListener("click", (e) => {
|
||||
if (
|
||||
e.target instanceof HTMLAnchorElement &&
|
||||
e.target.origin === document.location.origin &&
|
||||
e.target.pathname in routes // TODO: support params ... solid router を入れよう
|
||||
) {
|
||||
e.preventDefault();
|
||||
window.history.pushState({}, "", e.target.href);
|
||||
setPathname(e.target.pathname as keyof typeof routes);
|
||||
}
|
||||
});
|
||||
|
||||
window.addEventListener("popstate", () => {
|
||||
setPathname(document.location.pathname as keyof typeof routes);
|
||||
});
|
||||
|
||||
return () => (
|
||||
<>
|
||||
<header>
|
||||
<h1>Quot</h1>
|
||||
</header>
|
||||
{routes[pathname()] ?? <Page id={Number(pathname().slice(1))} />}
|
||||
</>
|
||||
);
|
||||
};
|
1
app/src/components/editor.tsx
Normal file
1
app/src/components/editor.tsx
Normal file
|
@ -0,0 +1 @@
|
|||
export default () => <>Editor (WIP)</>;
|
5
app/src/env.d.ts
vendored
Normal file
5
app/src/env.d.ts
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
interface ImportMeta {
|
||||
env: {
|
||||
QUOT_API_URL: string;
|
||||
};
|
||||
}
|
11
app/src/index.html
Normal file
11
app/src/index.html
Normal file
|
@ -0,0 +1,11 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="ja" dir="ltr">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<title>Quot</title>
|
||||
<link rel="stylesheet" href="/index.css" />
|
||||
<script type="module" src="/index.js"></script>
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
5
app/src/index.ts
Normal file
5
app/src/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
|||
import "@exampledev/new.css";
|
||||
import { render } from "solid-js/web";
|
||||
import App from "./app";
|
||||
|
||||
render(App, document.body);
|
27
app/src/pages/index.tsx
Normal file
27
app/src/pages/index.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import { createResource } from "solid-js";
|
||||
|
||||
type PagesResponse = Array<{
|
||||
id: number;
|
||||
title: string;
|
||||
text: string;
|
||||
created: string;
|
||||
updated: string;
|
||||
}>;
|
||||
|
||||
async function fetchPages(): Promise<PagesResponse> {
|
||||
const res = await fetch(
|
||||
new URL("/pages?order=updated.desc", import.meta.env.QUOT_API_URL)
|
||||
);
|
||||
const data = await res.json();
|
||||
return data as PagesResponse;
|
||||
}
|
||||
|
||||
export default () => {
|
||||
const [pages] = createResource("pages", fetchPages);
|
||||
|
||||
return (
|
||||
<main>
|
||||
<pre>{() => JSON.stringify(pages(), null, " ")}</pre>
|
||||
</main>
|
||||
);
|
||||
};
|
29
app/src/pages/page.tsx
Normal file
29
app/src/pages/page.tsx
Normal file
|
@ -0,0 +1,29 @@
|
|||
import { createResource } from "solid-js";
|
||||
import Editor from "../components/editor";
|
||||
|
||||
type PageResponse = {
|
||||
id: number;
|
||||
title: string;
|
||||
text: string;
|
||||
created: string;
|
||||
updated: string;
|
||||
};
|
||||
|
||||
async function fetchPage(id: number): Promise<PageResponse> {
|
||||
const res = await fetch(
|
||||
new URL(`/pages?id=eq.${id}`, import.meta.env.QUOT_API_URL)
|
||||
);
|
||||
const [data] = await res.json();
|
||||
return data as PageResponse;
|
||||
}
|
||||
|
||||
export default (props: { id: number }) => {
|
||||
const [page] = createResource(props.id, fetchPage);
|
||||
|
||||
return (
|
||||
<main>
|
||||
<Editor />
|
||||
<pre>{() => JSON.stringify(page(), null, " ")}</pre>
|
||||
</main>
|
||||
);
|
||||
};
|
56
app/src/server.ts
Normal file
56
app/src/server.ts
Normal file
|
@ -0,0 +1,56 @@
|
|||
import type { AddressInfo } from "node:net";
|
||||
import http from "node:http";
|
||||
import fs from "node:fs";
|
||||
import esbuild from "esbuild";
|
||||
|
||||
async function main() {
|
||||
const port = Number(process.env.PORT ?? "8080");
|
||||
const apiUrl = process.env.QUOT_API_URL || "http://localhost:3000/";
|
||||
const publicDir = __dirname;
|
||||
const htmlPath = `${publicDir}/index.html`;
|
||||
const scriptPath = `${publicDir}/index.ts`;
|
||||
|
||||
const result = await esbuild.serve(
|
||||
{
|
||||
host: "127.0.0.1",
|
||||
servedir: publicDir,
|
||||
},
|
||||
{
|
||||
bundle: true,
|
||||
minify: true,
|
||||
entryPoints: [scriptPath],
|
||||
define: {
|
||||
"import.meta.env.QUOT_API_URL": JSON.stringify(apiUrl),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
const handler: http.RequestListener = (req, res) => {
|
||||
const options = {
|
||||
hostname: result.host,
|
||||
port: result.port,
|
||||
path: req.url,
|
||||
method: req.method,
|
||||
headers: req.headers,
|
||||
};
|
||||
|
||||
const proxyReq = http.request(options, (proxyRes) => {
|
||||
if (proxyRes.statusCode === 200) {
|
||||
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
||||
proxyRes.pipe(res);
|
||||
} else {
|
||||
res.writeHead(200, { "Content-Type": "text/html" });
|
||||
fs.createReadStream(htmlPath).pipe(res);
|
||||
}
|
||||
});
|
||||
|
||||
req.pipe(proxyReq);
|
||||
};
|
||||
|
||||
const server = http.createServer(handler).listen(port);
|
||||
const address = server.address() as AddressInfo;
|
||||
|
||||
console.log(`http://0.0.0.0:${address.port}`);
|
||||
}
|
||||
|
||||
main();
|
9
app/tsconfig.json
Normal file
9
app/tsconfig.json
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"extends": "@tsconfig/node18-strictest-esm/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "dom.iterable"],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "solid-js/h",
|
||||
"noPropertyAccessFromIndexSignature": false
|
||||
}
|
||||
}
|
1
db/.gitignore
vendored
Normal file
1
db/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
.env
|
37
db/compose.yml
Normal file
37
db/compose.yml
Normal file
|
@ -0,0 +1,37 @@
|
|||
services:
|
||||
api:
|
||||
image: postgrest/postgrest:v10.0.0
|
||||
restart: unless-stopped
|
||||
ports: ["127.0.0.1:3000:3000"]
|
||||
environment:
|
||||
PGRST_DB_URI: postgresql://postgres:${POSTGRES_PASSWORD}@/postgres?host=/var/run/postgresql
|
||||
PGRST_DB_SCHEMA: public
|
||||
PGRST_DB_ANON_ROLE: postgres
|
||||
volumes:
|
||||
- postgres_socket:/var/run/postgresql
|
||||
depends_on:
|
||||
db:
|
||||
condition: service_healthy
|
||||
dbmate:
|
||||
image: amacneil/dbmate:1.15
|
||||
command: --wait up
|
||||
user: ${UID:-1000}:${GID:-1000}
|
||||
environment:
|
||||
DATABASE_URL: postgresql://postgres:${POSTGRES_PASSWORD}@/postgres?host=/var/run/postgresql
|
||||
volumes:
|
||||
- .:/db
|
||||
- postgres_socket:/var/run/postgresql
|
||||
depends_on: [db]
|
||||
db:
|
||||
image: postgres:14-alpine
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: pg_isready -U postgres
|
||||
environment:
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
volumes:
|
||||
- postgres_socket:/var/run/postgresql
|
||||
- postgres_data_v14:/var/lib/postgresql/data
|
||||
volumes:
|
||||
postgres_socket:
|
||||
postgres_data_v14:
|
23
db/migrations/0_init.sql
Normal file
23
db/migrations/0_init.sql
Normal file
|
@ -0,0 +1,23 @@
|
|||
-- migrate:up
|
||||
CREATE FUNCTION update_timestamp() RETURNS trigger LANGUAGE plpgsql AS $$
|
||||
BEGIN
|
||||
NEW.updated = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TABLE pages (
|
||||
id SERIAL PRIMARY KEY,
|
||||
title TEXT NOT NULL UNIQUE,
|
||||
text TEXT NOT NULL,
|
||||
created TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TRIGGER pages_updated BEFORE UPDATE ON pages FOR EACH ROW
|
||||
EXECUTE PROCEDURE update_timestamp();
|
||||
|
||||
-- migrate:down
|
||||
DROP TRIGGER pages_updated ON pages;
|
||||
DROP TABLE pages;
|
||||
DROP FUNCTION update_timestamp();
|
120
db/schema.sql
Normal file
120
db/schema.sql
Normal file
|
@ -0,0 +1,120 @@
|
|||
SET statement_timeout = 0;
|
||||
SET lock_timeout = 0;
|
||||
SET idle_in_transaction_session_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SELECT pg_catalog.set_config('search_path', '', false);
|
||||
SET check_function_bodies = false;
|
||||
SET xmloption = content;
|
||||
SET client_min_messages = warning;
|
||||
SET row_security = off;
|
||||
|
||||
--
|
||||
-- Name: update_timestamp(); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE FUNCTION public.update_timestamp() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
NEW.updated = CURRENT_TIMESTAMP;
|
||||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
|
||||
--
|
||||
-- Name: pages; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.pages (
|
||||
id integer NOT NULL,
|
||||
title text NOT NULL,
|
||||
text text NOT NULL,
|
||||
created timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated timestamp with time zone DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: pages_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.pages_id_seq
|
||||
AS integer
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: pages_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.pages_id_seq OWNED BY public.pages.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.schema_migrations (
|
||||
version character varying(255) NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: pages id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.pages ALTER COLUMN id SET DEFAULT nextval('public.pages_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: pages pages_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.pages
|
||||
ADD CONSTRAINT pages_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: pages pages_title_key; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.pages
|
||||
ADD CONSTRAINT pages_title_key UNIQUE (title);
|
||||
|
||||
|
||||
--
|
||||
-- Name: schema_migrations schema_migrations_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.schema_migrations
|
||||
ADD CONSTRAINT schema_migrations_pkey PRIMARY KEY (version);
|
||||
|
||||
|
||||
--
|
||||
-- Name: pages pages_updated; Type: TRIGGER; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TRIGGER pages_updated BEFORE UPDATE ON public.pages FOR EACH ROW EXECUTE FUNCTION public.update_timestamp();
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
|
||||
--
|
||||
-- Dbmate schema migrations
|
||||
--
|
||||
|
||||
INSERT INTO public.schema_migrations (version) VALUES
|
||||
('0');
|
Loading…
Add table
Reference in a new issue