chore: everything gone

This commit is contained in:
2024-04-28 16:41:29 +02:00
parent 47ea9d6e61
commit f76367835f
60 changed files with 0 additions and 6058 deletions

View File

@@ -1,25 +0,0 @@
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
// README at: https://github.com/devcontainers/templates/tree/main/src/typescript-node
{
"name": "Node.js & TypeScript",
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
"image": "mcr.microsoft.com/devcontainers/typescript-node:0-20",
// Features to add to the dev container. More info: https://containers.dev/features.
// "features": {},
// Use 'forwardPorts' to make a list of ports inside the container available locally.
"forwardPorts": [4000],
// Use 'postCreateCommand' to run commands after the container is created.
"postCreateCommand": "bash ./apps/api/util/setup.sh",
// Configure tool-specific properties.
// "customizations": {},
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
// "remoteUser": "root"
"features": {
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
}
}

15
.gitignore vendored
View File

@@ -1,15 +0,0 @@
node_modules
*.env
/apps/api/repos
/repos
dist
/ssh
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions
!.yarn/cache
# .pnp.*

View File

@@ -1,5 +0,0 @@
{
"recommendations": [
"arcanis.vscode-zipfs"
]
}

View File

@@ -1,9 +0,0 @@
{
"dotenv.enableAutocloaking": false,
"search.exclude": {
"**/.yarn": true,
"**/.pnp.*": true
},
"typescript.tsdk": ".yarn/sdks/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +0,0 @@
# This file is automatically generated by @yarnpkg/sdks.
# Manual changes might be lost!
integrations:
- vscode

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/bin/tsc
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/bin/tsc your application uses
module.exports = absRequire(`typescript/bin/tsc`);

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/bin/tsserver
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/bin/tsserver your application uses
module.exports = absRequire(`typescript/bin/tsserver`);

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsc.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsc.js your application uses
module.exports = absRequire(`typescript/lib/tsc.js`);

View File

@@ -1,225 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const moduleWrapper = tsserver => {
if (!process.versions.pnp) {
return tsserver;
}
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
// before forwarding it to TS, and to add it back on all returned paths.
function toEditorPath(str) {
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
// We also take the opportunity to turn virtual paths into physical ones;
// this makes it much easier to work with workspaces that list peer
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
// file instances instead of the real ones.
//
// We only do this to modules owned by the the dependency tree roots.
// This avoids breaking the resolution when jumping inside a vendor
// with peer dep (otherwise jumping into react-dom would show resolution
// errors on react).
//
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
str = normalize(str);
if (str.match(/\.zip\//)) {
switch (hostInfo) {
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
// VSCode only adds it automatically for supported schemes,
// so we have to do it manually for the `zip` scheme.
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
//
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
//
// 2021-10-08: VSCode changed the format in 1.61.
// Before | ^zip:/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
// 2022-04-06: VSCode changed the format in 1.66.
// Before | ^/zip//c:/foo/bar.zip/package.json
// After | ^/zip/c:/foo/bar.zip/package.json
//
// 2022-05-06: VSCode changed the format in 1.68
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default: {
str = `zip:${str}`;
} break;
}
} else {
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
}
}
return str;
}
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
// Force enable 'allowLocalPluginLoads'
// TypeScript tries to resolve plugins using a path relative to itself
// which doesn't work when using the global cache
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
// And here is the point where we hijack the VSCode <-> TS communications
// by adding ourselves in the middle. We locate everything that looks
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
parsedMessage != null &&
typeof parsedMessage === `object` &&
parsedMessage.arguments &&
typeof parsedMessage.arguments.hostInfo === `string`
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
hostInfo += ` <1.61`;
} else if (minor < 66) {
hostInfo += ` <1.66`;
} else if (minor < 68) {
hostInfo += ` <1.68`;
}
}
}
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;
};
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsserver.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsserver.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserver.js`));

View File

@@ -1,225 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
const moduleWrapper = tsserver => {
if (!process.versions.pnp) {
return tsserver;
}
const {isAbsolute} = require(`path`);
const pnpApi = require(`pnpapi`);
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
const isPortal = str => str.startsWith("portal:/");
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
return `${locator.name}@${locator.reference}`;
}));
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
// doesn't understand. This layer makes sure to remove the protocol
// before forwarding it to TS, and to add it back on all returned paths.
function toEditorPath(str) {
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
// We also take the opportunity to turn virtual paths into physical ones;
// this makes it much easier to work with workspaces that list peer
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
// file instances instead of the real ones.
//
// We only do this to modules owned by the the dependency tree roots.
// This avoids breaking the resolution when jumping inside a vendor
// with peer dep (otherwise jumping into react-dom would show resolution
// errors on react).
//
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
if (resolved) {
const locator = pnpApi.findPackageLocator(resolved);
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
str = resolved;
}
}
str = normalize(str);
if (str.match(/\.zip\//)) {
switch (hostInfo) {
// Absolute VSCode `Uri.fsPath`s need to start with a slash.
// VSCode only adds it automatically for supported schemes,
// so we have to do it manually for the `zip` scheme.
// The path needs to start with a caret otherwise VSCode doesn't handle the protocol
//
// Ref: https://github.com/microsoft/vscode/issues/105014#issuecomment-686760910
//
// 2021-10-08: VSCode changed the format in 1.61.
// Before | ^zip:/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
// 2022-04-06: VSCode changed the format in 1.66.
// Before | ^/zip//c:/foo/bar.zip/package.json
// After | ^/zip/c:/foo/bar.zip/package.json
//
// 2022-05-06: VSCode changed the format in 1.68
// Before | ^/zip/c:/foo/bar.zip/package.json
// After | ^/zip//c:/foo/bar.zip/package.json
//
case `vscode <1.61`: {
str = `^zip:${str}`;
} break;
case `vscode <1.66`: {
str = `^/zip/${str}`;
} break;
case `vscode <1.68`: {
str = `^/zip${str}`;
} break;
case `vscode`: {
str = `^/zip/${str}`;
} break;
// To make "go to definition" work,
// We have to resolve the actual file system path from virtual path
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
case `coc-nvim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = resolve(`zipfile:${str}`);
} break;
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
// We have to resolve the actual file system path from virtual path,
// everything else is up to neovim
case `neovim`: {
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
str = `zipfile://${str}`;
} break;
default: {
str = `zip:${str}`;
} break;
}
} else {
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
}
}
return str;
}
function fromEditorPath(str) {
switch (hostInfo) {
case `coc-nvim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
// So in order to convert it back, we use .* to match all the thing
// before `zipfile:`
return process.platform === `win32`
? str.replace(/^.*zipfile:\//, ``)
: str.replace(/^.*zipfile:/, ``);
} break;
case `neovim`: {
str = str.replace(/\.zip::/, `.zip/`);
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
return str.replace(/^zipfile:\/\//, ``);
} break;
case `vscode`:
default: {
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
} break;
}
}
// Force enable 'allowLocalPluginLoads'
// TypeScript tries to resolve plugins using a path relative to itself
// which doesn't work when using the global cache
// https://github.com/microsoft/TypeScript/blob/1b57a0395e0bff191581c9606aab92832001de62/src/server/project.ts#L2238
// VSCode doesn't want to enable 'allowLocalPluginLoads' due to security concerns but
// TypeScript already does local loads and if this code is running the user trusts the workspace
// https://github.com/microsoft/vscode/issues/45856
const ConfiguredProject = tsserver.server.ConfiguredProject;
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
this.projectService.allowLocalPluginLoads = true;
return originalEnablePluginsWithOptions.apply(this, arguments);
};
// And here is the point where we hijack the VSCode <-> TS communications
// by adding ourselves in the middle. We locate everything that looks
// like an absolute path of ours and normalize it.
const Session = tsserver.server.Session;
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
let hostInfo = `unknown`;
Object.assign(Session.prototype, {
onMessage(/** @type {string | object} */ message) {
const isStringMessage = typeof message === 'string';
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
if (
parsedMessage != null &&
typeof parsedMessage === `object` &&
parsedMessage.arguments &&
typeof parsedMessage.arguments.hostInfo === `string`
) {
hostInfo = parsedMessage.arguments.hostInfo;
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
// The RegExp from https://semver.org/ but without the caret at the start
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
) ?? []).map(Number)
if (major === 1) {
if (minor < 61) {
hostInfo += ` <1.61`;
} else if (minor < 66) {
hostInfo += ` <1.66`;
} else if (minor < 68) {
hostInfo += ` <1.68`;
}
}
}
}
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
return typeof value === 'string' ? fromEditorPath(value) : value;
});
return originalOnMessage.call(
this,
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
);
},
send(/** @type {any} */ msg) {
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
return typeof value === `string` ? toEditorPath(value) : value;
})));
}
});
return tsserver;
};
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript/lib/tsserverlibrary.js
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript/lib/tsserverlibrary.js your application uses
module.exports = moduleWrapper(absRequire(`typescript/lib/tsserverlibrary.js`));

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env node
const {existsSync} = require(`fs`);
const {createRequire} = require(`module`);
const {resolve} = require(`path`);
const relPnpApiPath = "../../../../.pnp.cjs";
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
const absRequire = createRequire(absPnpApiPath);
if (existsSync(absPnpApiPath)) {
if (!process.versions.pnp) {
// Setup the environment to be able to require typescript
require(absPnpApiPath).setup();
}
}
// Defer to the real typescript your application uses
module.exports = absRequire(`typescript`);

View File

@@ -1,10 +0,0 @@
{
"name": "typescript",
"version": "5.3.3-sdk",
"main": "./lib/typescript.js",
"type": "commonjs",
"bin": {
"tsc": "./bin/tsc",
"tsserver": "./bin/tsserver"
}
}

View File

@@ -1,9 +0,0 @@
yarnPath: .yarn/releases/yarn-4.0.2.cjs
packageExtensions:
"drizzle-kit@*":
dependencies:
"drizzle-orm": "*"
"@drizzle-team/studio@*":
dependencies:
"drizzle-orm": "*"
nodeLinker: node-modules

View File

@@ -1,18 +0,0 @@
# sern automata
sern Automata is a github bot used to automate stuff in the organization.
It's written in Typescript and it's basically an express server that listens to github webhooks.
## Features
- [x] **Jobs**: Jobs are groups of bash scripts that are executed inside the docker container that runs the bot.
- [ ] **PR Automations**: Commands that can be executed to check if a PR is valid, to add labels, reviewers...
- [ ] **Issue Automations**: Commands that can be executed to check if an issue is valid, to add labels, assignees...
## Development
We use a devcontainer to develop the bot, but there will be no documentation to set up a development environment at the moment.
## Deployment
Everything is directly hosted at [Railway](https://railway.app/). The bot is deployed using a docker container (see `Dockerfile.api`).

View File

@@ -1,4 +0,0 @@
{
"tabWidth": 4,
"useTabs": true
}

View File

@@ -1,16 +0,0 @@
FROM node:lts-alpine
RUN apk add git bash curl
RUN bash < <(curl -s https://raw.githubusercontent.com/babashka/babashka/master/install)
WORKDIR /app
COPY . .
RUN bash ./util/setup.sh
RUN npm install
RUN npm run build
CMD node dist/index.js

View File

@@ -1,12 +0,0 @@
# automata
A github bot for automating github related stuff
a javascript rewrite by @SrIzan10
the repo is literally a collection of bash scripts that get run when certain stuff happens
# on development
use the devcontainer
don't use windows, use wsl instead
prs might not be accepted if the code isn't understandable enough due to safety and security reasons

View File

@@ -1,21 +0,0 @@
(require '[babashka.http-client :as http]
'[cheshire.core :as json])
(def token (get env "GHTOKEN"))
(defn latest-version [sern-repo]
(-> (http/get
(str "https://api.github.com/repos/sern-handler/" sern-repo "/tags")
{:headers
{"Accept" "application/vnd.github+json"}
{"X-GitHub-Api-Version" "2022-11-28"}
{"Authorization" (str "Bearer " token)}
}
)
:body
(json/parse-string true)
first
:name))
(def versions (mapv latest-version *command-line-args*))
(println (clojure.string/join ", " versions))

View File

@@ -1,5 +0,0 @@
(def now (java.time.ZonedDateTime/now))
(def LA-timezone (java.time.ZoneId/of "America/Los_Angeles"))
(def LA-time (.withZoneSameInstant now LA-timezone))
(def pattern (java.time.format.DateTimeFormatter/ofPattern "HH:mm"))
(println (.format LA-time pattern))

View File

@@ -1,3 +0,0 @@
[
{ "file": "pst.clj", "route": "/bb/getPstTime", "method": "GET" }
]

View File

@@ -1,274 +0,0 @@
import express from 'express';
import 'dotenv/config';
import { execa } from 'execa';
import validateJsonWebhook from './plugins/validateJsonWebhook.js';
import { FeedbackRequestBody, FeedbackRequestBodySchema, Logs } from './util/types.js';
import cors from 'cors'
import rateLimit from 'express-rate-limit';
import { Webhook } from 'simple-discord-webhooks';
import { codeBlock } from './util/discordCodeBlock.js';
import db, { schema } from 'database/dist/index.js';
import jobs from './jobs.js';
import expressWs from 'express-ws';
import resolvePlugins from './util/resolvePlugins.js';
import { stripIndents } from 'common-tags';
const devMode = process.argv[2] === '--dev';
if (devMode) console.log('You\'re a developer 😎 (sorry for that emoji jumpscare)')
const cwd = process.cwd()
console.log('Setting correct permissions for Github SSH key...')
await execa('chmod', ['-R', '400', '/ssh'], { shell: true })
console.log('Permissions done!')
const { app } = expressWs(express())
app.use(express.json())
app.use(cors())
const feedbackRateLimit = rateLimit({
windowMs: 5 * 60 * 1000,
max: 10,
standardHeaders: 'draft-7',
legacyHeaders: true,
})
app.get('/', (req, res) => {
res.send('hi this is the api what did you even expect')
})
let jobRunning = false
for (const job of jobs) {
switch (job.method) {
case "POST":
app.post(job.route, async (req, res) => {
await expressCode(req, res);
});
break;
case "GET":
app.get(job.route, async (req, res) => {
await expressCode(req, res);
});
break;
}
const expressCode = async (req: express.Request, res: express.Response) => {
const pluginsResult = await resolvePlugins(job.plugins, req, res);
if (pluginsResult.includes(false)) {
return res.status(418).send({ success: false, message: "Plugins didn't pass" });
}
res.send({ success: true, message: "Command is running" });
jobRunning = true;
const parse_payload = (level: 'info' | 'error', payload: any) => ({
timestamp: new Date(),
message: payload.toString(),
level
})
const jobLogs = [] as { step: number, logs: Logs[] }[]
let jobSuccessful = true
try {
for (let i = 0; i < job.steps.length; i++) {
const steps = job.steps[i]!;
const logsToPush = [] as Logs[];
console.log(`Running step ${steps.name}`);
const cmd = execa(
"bash",
[`${cwd}/scripts/${job.stepsMainDir}/${steps.script}`],
{
cwd: steps.cwd.startsWith('repos/') ? `${cwd}/../../${steps.cwd}` : steps.cwd,
shell: true,
env: {
NT_ARGS: JSON.stringify({
...job.cmdArgs,
requestBody: req.body,
})
},
},
)
cmd.stdout!.on('data', (data) => logsToPush.push(parse_payload('info', data.toString().replace(/\n$/, ""))));
cmd.stderr!.on('data', (data) => logsToPush.push(parse_payload('error', data.toString().replace(/\n$/, ""))));
await new Promise((resolve, reject) => {
cmd.once('exit', (code) => {
if (code === 0 || !code) {
console.log(`Step ${steps.name} finished successfully`);
logsToPush.push(parse_payload('info', 'Step finished successfully'));
jobLogs.push({ step: steps.id, logs: logsToPush });
jobSuccessful = true;
resolve('nice');
} else {
console.log(`Step ${steps.name} failed with code ${code}`);
logsToPush.push(parse_payload('error', `Step failed with code ${code}`));
jobLogs.push({ step: steps.id, logs: logsToPush });
jobSuccessful = false;
reject('stop it');
}
});
});
}
} catch {}
jobRunning = false
const markdownText = stripIndents`
# Job ${job.name} finished
## Steps
${jobLogs.map((step) => {
return `### Step ${step.step}: ${job.steps.find(s => s.id === step.step)?.name}\n\`\`\`\n${step.logs.map((log) => {
return `${log.timestamp.toISOString()} - ${log.level.toUpperCase()} | ${log.message}`;
}).join('\n')}\n\`\`\``;
}).join('\n')}
`;
const createSnippet = await fetch(`${process.env.SERN_BIN_ENDPOINT}/api/create`, {
method: 'POST',
headers: {
'Authorization': process.env.SERN_BIN_KEY!,
},
body: JSON.stringify({
fileName: `run-${job.name}-${new Date().toISOString()}.md`,
description: `Logs for ${job.name} job`,
authorId: process.env.SERN_BIN_USER,
lang: "markdown",
code: markdownText
})
}).then(async res => (await res.text()).replaceAll('"', ''))
const dbWrite = (await db.insert(schema.jobsList).values({
name: job.name,
steps: job.steps,
sernbinid: createSnippet
}).returning())[0]
const webhook = new Webhook(new URL(process.env.AUTOMATA_CHANNEL_WEBHOOK!), 'Job Logs (by automata)', 'https://avatars.githubusercontent.com/u/129876409?v=4')
webhook.send(`Job #${dbWrite?.id} ${job.name} finished`, [{
color: jobSuccessful ? 0x00ff00 : 0xff0000,
description: `Job ${job.name} finished with ${jobSuccessful ? 'no errors' : 'errors'}`,
fields: [
{ name: 'Snippet', value: `[Here](https://bin.sern.dev/s/${createSnippet})`, inline: true },
],
}])
}
};
app.post('/wh/updateDocsJson', async (req, res) => {
const validate = validateJsonWebhook(req)
if (!validate) {
res.status(403).send({
success: false,
error: 'Invalid token'
})
return
}
if (req.body.action !== 'released') {
res.send({
success: true,
error: 'Token valid, but ignoring action...'
})
// this line fixed the entire instability of automata
return;
}
const cmd = execa('bash', ['scripts/updateDocsJson.sh', process.env.GHTOKEN!, process.env.EMAIL!], { shell: true })
cmd.stdout!.on('data', (data) => console.log(JSON.stringify(data.toString())))
cmd.stderr!.on('data', (data) => console.log(JSON.stringify(data.toString())))
res.send({
success: true,
message: "command is running"
})
})
app.post('/tutorial/feedback', feedbackRateLimit, async (req, res) => {
const body = req.body as FeedbackRequestBody
// validation of request body
try {
FeedbackRequestBodySchema.parse(body)
} catch {
return res
.status(400)
.send({
successful: false,
error: "You have something missing in your request!",
});
}
if (body.feedback !== "up" && body.feedback !== "down")
return res
.status(400)
.send({
successful: false,
error: "Feedback must be either 'up' or 'down'!",
});
if (!body.route.startsWith('/docs/tutorial'))
return res
.status(400)
.send({
successful: false,
error: "Are you sure you didn't modify this request?",
});
// part where turnstile token gets validated
const turnstileFormData = new URLSearchParams()
turnstileFormData.append('response', body.turnstileToken)
turnstileFormData.append('secret', process.env.TURNSTILE_SECRET_DEV!)
const turnstileResponse = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
method: 'POST',
body: turnstileFormData
}).then(res => res.json())
if (!turnstileResponse.success)
return res
.status(403)
.send({
successful: false,
error: "Turnstile verificaion not successful",
});
// actual database recording
const trimmedRoute = body.route.replace('/docs/tutorial', '')
const data = {
id: crypto.randomUUID(),
feedback: body.feedback,
route: trimmedRoute,
inputText: body.inputText,
}
await db.insert(schema.guideFeedback).values(data).execute()
res.send({
successful: true,
message: "Feedback recorded!",
});
// webhook
const webhook = new Webhook(new URL(process.env.DEV_WEBHOOK!), 'Guide Feedback (by automata)', 'https://avatars.githubusercontent.com/u/129876409?v=4')
// const upvoteCount = (await pb.collection('feedback').getFullList({ filter: `feedback = 'up' && route = '${body.route}'` })).length
// const downvoteCount = (await pb.collection('feedback').getFullList({ filter: `feedback = 'down' && route = '${body.route}'` })).length
const upvoteCount = (await (db.query.guideFeedback!.findMany({
where: (guideFeedback, { eq, and }) => and(
eq(guideFeedback.feedback, 'up'),
eq(guideFeedback.route, trimmedRoute)
),
})).execute()).length
const downvoteCount = (await (db.query.guideFeedback!.findMany({
where: (guideFeedback, { eq, and }) => and(
eq(guideFeedback.feedback, 'down'),
eq(guideFeedback.route, trimmedRoute)
),
})).execute()).length
webhook.send(`Feedback recorded for ${body.route}!`, [{
color: body.feedback === 'up' ? 0x00ff00 : 0xff0000,
description: body.inputText ? codeBlock(body.inputText) : undefined,
fields: [
{ name: 'Ratio', value: `${(upvoteCount / (upvoteCount + downvoteCount) * 100).toFixed(2)}%`, inline: true },
{ name: 'Upvotes', value: upvoteCount.toString(), inline: true },
{ name: 'Downvotes', value: downvoteCount.toString(), inline: true },
]
}])
})
app.get('/ping', (req, res) => {
res.send('Pong')
})
const port = Number(process.env.PORT!) || 4000
app.listen(port, '0.0.0.0', () => {
console.log(`Server listening on [::]${port}`)
})

View File

@@ -1,119 +0,0 @@
export default [
{
name: 'Update docs',
method: 'POST',
route: '/wh/updateDocs',
plugins: [],
cmdArgs: {
githubToken: process.env.GHTOKEN!,
email: process.env.EMAIL!
},
stepsMainDir: 'updateDocs',
steps: [
{
id: 1,
name: 'Move docusaurus config files',
cwd: 'repos/website',
script: 'moveFiles.sh'
},
{
id: 2,
name: 'Build docs',
cwd: 'repos/website',
script: 'buildWebsite.sh'
},
{
id: 3,
name: 'Revert moved config files',
cwd: 'repos/website',
script: 'revertMovedFiles.sh'
},
{
id: 4,
name: 'Generate Typedoc JSON',
cwd: 'repos/website',
script: 'typedocJson.sh'
},
{
id: 5,
name: 'Push website',
cwd: 'repos/website',
script: 'pushWebsite.sh'
},
{
id: 6,
name: 'Push community bot',
cwd: 'repos/sern-community',
script: 'pushCommunityBot.sh'
}
]
},
{
name: 'Test',
method: 'GET',
route: '/test',
plugins: ['apiToken'],
cmdArgs: {
randomVariable: 'hey this is a variable'
},
stepsMainDir: 'test',
steps: [
{
id: 1,
name: 'Hello world',
cwd: 'scripts/test',
script: 'test.sh'
},
{
id: 2,
name: 'Hello world from variable',
cwd: 'scripts/test',
script: 'variable.sh'
}
]
},
{
name: 'git pull repo',
method: 'POST',
route: '/wh/push',
plugins: ['validateJsonWebhook', 'gitRepoExists'],
cmdArgs: {},
stepsMainDir: 'gitPull',
steps: [
{
id: 1,
name: 'Run git pull',
cwd: 'repos',
script: 'gitPull.sh'
}
]
}
] satisfies Jobs[]
export interface Jobs {
name: string;
method: 'GET' | 'POST';
route: string;
plugins: string[];
cmdArgs: Record<string, string>;
stepsMainDir: string;
steps: Step[];
}
export interface Step {
id: number;
name: string;
cwd: string;
script: string
}
export interface Logs {
timestamp: Date;
message: string;
level: 'info' | 'error';
}
export interface LogGroup {
stepId: string;
logs: Logs[];
}

View File

@@ -1,33 +0,0 @@
{
"name": "api",
"version": "1.0.0",
"scripts": {
"dev": "tsc-watch --preserveWatchOutput --onSuccess \"node dist/index.js --dev\"",
"build": "tsc",
"start": "node dist/index.js"
},
"type": "module",
"dependencies": {
"body-parser": "^1.20.2",
"common-tags": "^1.8.2",
"cors": "^2.8.5",
"database": "1.0.0",
"dotenv": "^16.0.3",
"execa": "^7.1.1",
"express": "^4.18.2",
"express-rate-limit": "^6.11.1",
"express-ws": "^5.0.2",
"redis": "^4.6.13",
"simple-discord-webhooks": "^2.1.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@types/common-tags": "^1.8.4",
"@types/cors": "^2.8.14",
"@types/express": "^4.17.17",
"@types/express-ws": "^3.0.4",
"@types/node": "^18.15.11",
"tsc-watch": "^6.0.0",
"typescript": "^5.0.4"
}
}

View File

@@ -1,5 +0,0 @@
import { Request } from "express";
export default async function ApiToken(request: Request, _response?: Response) {
return request.headers["Authorization"] === process.env.API_TOKEN
}

View File

@@ -1,6 +0,0 @@
import type { Request, Response } from "express";
export default async function ghRepoExists(request: Request, _response: Response) {
console.log(request.body.repository)
return false
}

View File

@@ -1,15 +0,0 @@
import type { Request, Response } from "express";
import * as crypto from 'crypto';
export default async function validateJsonWebhook(request: Request, _response?: Response) {
// calculate the signature
const expectedSignature = "sha256=" +
crypto.createHmac("sha256", process.env.JSONWEBHOOK_TOKEN!)
.update(JSON.stringify(request.body))
.digest("hex");
// compare the signature against the one in the request
const signature = request.headers["x-hub-signature-256"];
return signature === expectedSignature
}

View File

@@ -1,38 +0,0 @@
#!/bin/bash
REPO=$(echo $NT_ARGS | jq -r '.requestBody.repository.name')
if [ -z "$REPO" ]; then
echo "No repository provided"
exit 1
fi
case $REPO in
"handler")
echo "Pulling handler"
cd sernHandlerV2
git pull
;;
"website")
echo "Pulling website"
cd website
git pull
;;
"sern-community")
echo "Pulling sern-community"
cd sern-community
git pull
;;
"atm-playground")
echo "Got playground"
;;
*)
echo "Invalid repository provided: $REPO"
exit 1
esac
if [ -z "$(git diff --name-only HEAD~1 HEAD | grep package.json)" ]; then
echo "No changes in package.json"
else
echo "Changes in package.json"
yarn install
fi

View File

@@ -1 +0,0 @@
echo "hi"

View File

@@ -1,3 +0,0 @@
RANDOMVARIABLE=$(echo $NT_ARGS | jq -r '.randomVariable')
echo $RANDOMVARIABLE

View File

@@ -1 +0,0 @@
yarn build

View File

@@ -1,2 +0,0 @@
mv ./docusaurus.config.js ./original.docusaurus.config.js
mv ./docgen.docusaurus.config.js ./docusaurus.config.js

View File

@@ -1,7 +0,0 @@
GITHUBTOKEN=$(echo $NT_ARGS | jq ".githubToken")
EMAIL=$(echo $NT_ARGS | jq ".email")
git add .
git -c user.name="sern bot" -c user.email="$EMAIL" commit -m "chore: update api documentation"
git remote set-url origin git@github.com:sern-handler/sern-community.git
git push --force

View File

@@ -1,7 +0,0 @@
GITHUBTOKEN=$(echo $NT_ARGS | jq ".githubToken")
EMAIL=$(echo $NT_ARGS | jq ".email")
git add .
git -c user.name="sern bot" -c user.email="$EMAIL" commit -m "chore: update api documentation"
git remote set-url origin git@github.com:sern-handler/website.git
git push --force

View File

@@ -1,2 +0,0 @@
mv docusaurus.config.js docgen.docusaurus.config.js
mv original.docusaurus.config.js docusaurus.config.js

View File

@@ -1 +0,0 @@
yarn typedoc-json

View File

@@ -1,14 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": ".",
},
"include": [
"**/*.ts"
],
"exclude": [
"repos",
"dist"
]
}

View File

@@ -1,4 +0,0 @@
// definitely not stolen from discord.js :clueless:
export function codeBlock(language: string, content?: string): string {
return content === undefined ? `\`\`\`\n${language}\n\`\`\`` : `\`\`\`${language}\n${content}\n\`\`\``;
}

View File

@@ -1,18 +0,0 @@
import type { Request, Response } from "express"
export default async function resolvePlugins(plugins: string[], req: Request, res: Response) {
if (plugins.length === 0)
// not doing any crazy stuff today sorry
return [true]
const resolvedPlugins: boolean[] = []
plugins.forEach(async (plugin) => {
const resolvedPlugin = await import(`../plugins/${plugin}.js`)
.then(async (plugin) => await plugin.default(req, res) as boolean)
.catch(() => {
console.error(`Plugin ${plugin} doesn't exist`)
return false
})
resolvedPlugins.push(resolvedPlugin)
})
return resolvedPlugins
}

View File

@@ -1,72 +0,0 @@
#!/bin/bash
echo "SERN AUTOMATA SETUP SCRIPT"
rm -rf repos/
echo -ne "Creating repos folder"
mkdir repos
cd repos
echo " done"
if [ -x "$(command -v sern)" ]; then
echo "sern CLI already installed"
else
echo -ne "Installing sern CLI"
npm install -g @sern/cli
echo " done"
fi
echo "Cloning repos"
# handler (clone it as sernHandlerV2)
echo -ne "- handler"
git clone https://github.com/sern-handler/handler.git sernHandlerV2/ > /dev/null 2>&1
echo " done"
# website
echo -ne "- website"
git clone https://github.com/sern-handler/website.git > /dev/null 2>&1
echo " done"
# sern community discord bot
echo -ne "- discord bot"
git clone https://github.com/sern-handler/sern-community.git > /dev/null 2>&1
echo " done"
echo -ne "Installing yarn"
npm install -g yarn > /dev/null 2>&1
echo " done"
echo "Installing npm packages"
# website
echo -ne "- website"
cd website
echo -ne " (resetting yarn lock)"
# this had to be done
rm yarn.lock
touch yarn.lock
yarn > /dev/null 2>&1
cd ..
echo " done both"
# handler
echo -ne "- handler"
cd sernHandlerV2
yarn > /dev/null 2>&1
cd ..
echo " done"
# discord bot
echo -ne "- discord bot"
cd sern-community
yarn > /dev/null 2>&1
cd ..
echo " done"
echo "SSH keys part"
echo -ne "Adding ssh config"
rm ~/.ssh/config
mkdir ~/.ssh
cp ./ssh.conf ~/.ssh/config
echo " done"
# go back to the initial folder (for development purposes)
cd ..

View File

@@ -1 +0,0 @@
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

View File

@@ -1,15 +0,0 @@
import { z } from "zod";
export const FeedbackRequestBodySchema = z.object({
turnstileToken: z.string().min(1),
feedback: z.enum(['up', 'down']),
inputText: z.string().optional(),
route: z.string(),
})
export type FeedbackRequestBody = z.infer<typeof FeedbackRequestBodySchema>
export interface Logs {
timestamp: Date;
message: string;
level: 'info' | 'error';
}

View File

@@ -1 +0,0 @@
# database

View File

@@ -1,60 +0,0 @@
CREATE TABLE IF NOT EXISTS "account" (
"userId" text NOT NULL,
"type" text NOT NULL,
"provider" text NOT NULL,
"providerAccountId" text NOT NULL,
"refresh_token" text,
"access_token" text,
"expires_at" integer,
"token_type" text,
"scope" text,
"id_token" text,
"session_state" text,
CONSTRAINT "account_provider_providerAccountId_pk" PRIMARY KEY("provider","providerAccountId")
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "guideFeedback" (
"id" text PRIMARY KEY NOT NULL,
"feedback" text NOT NULL,
"route" text NOT NULL,
"inputText" text
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "jobsList" (
"id" bigserial PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"steps" json NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "session" (
"sessionToken" text PRIMARY KEY NOT NULL,
"userId" text NOT NULL,
"expires" timestamp NOT NULL
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "user" (
"id" text PRIMARY KEY NOT NULL,
"name" text,
"email" text NOT NULL,
"emailVerified" timestamp,
"image" text
);
--> statement-breakpoint
CREATE TABLE IF NOT EXISTS "verificationToken" (
"identifier" text NOT NULL,
"token" text NOT NULL,
"expires" timestamp NOT NULL,
CONSTRAINT "verificationToken_identifier_token_pk" PRIMARY KEY("identifier","token")
);
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "account" ADD CONSTRAINT "account_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;
--> statement-breakpoint
DO $$ BEGIN
ALTER TABLE "session" ADD CONSTRAINT "session_userId_user_id_fk" FOREIGN KEY ("userId") REFERENCES "user"("id") ON DELETE cascade ON UPDATE no action;
EXCEPTION
WHEN duplicate_object THEN null;
END $$;

View File

@@ -1 +0,0 @@
ALTER TABLE "jobsList" ADD COLUMN "sernbinid" text NOT NULL;

View File

@@ -1,4 +0,0 @@
DROP TABLE "account";--> statement-breakpoint
DROP TABLE "session";--> statement-breakpoint
DROP TABLE "user";--> statement-breakpoint
DROP TABLE "verificationToken";

View File

@@ -1,293 +0,0 @@
{
"id": "5175ce72-68af-4e42-a300-0557071eb623",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "5",
"dialect": "pg",
"tables": {
"account": {
"name": "account",
"schema": "",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider": {
"name": "provider",
"type": "text",
"primaryKey": false,
"notNull": true
},
"providerAccountId": {
"name": "providerAccountId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"token_type": {
"name": "token_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"session_state": {
"name": "session_state",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"account_userId_user_id_fk": {
"name": "account_userId_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"account_provider_providerAccountId_pk": {
"name": "account_provider_providerAccountId_pk",
"columns": [
"provider",
"providerAccountId"
]
}
},
"uniqueConstraints": {}
},
"guideFeedback": {
"name": "guideFeedback",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"feedback": {
"name": "feedback",
"type": "text",
"primaryKey": false,
"notNull": true
},
"route": {
"name": "route",
"type": "text",
"primaryKey": false,
"notNull": true
},
"inputText": {
"name": "inputText",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"jobsList": {
"name": "jobsList",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"steps": {
"name": "steps",
"type": "json",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"session": {
"name": "session",
"schema": "",
"columns": {
"sessionToken": {
"name": "sessionToken",
"type": "text",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_userId_user_id_fk": {
"name": "session_userId_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"user": {
"name": "user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"emailVerified": {
"name": "emailVerified",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"verificationToken": {
"name": "verificationToken",
"schema": "",
"columns": {
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"verificationToken_identifier_token_pk": {
"name": "verificationToken_identifier_token_pk",
"columns": [
"identifier",
"token"
]
}
},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,299 +0,0 @@
{
"id": "63e42e23-78aa-4b67-96a2-9b1bc6bf15c8",
"prevId": "5175ce72-68af-4e42-a300-0557071eb623",
"version": "5",
"dialect": "pg",
"tables": {
"account": {
"name": "account",
"schema": "",
"columns": {
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"type": {
"name": "type",
"type": "text",
"primaryKey": false,
"notNull": true
},
"provider": {
"name": "provider",
"type": "text",
"primaryKey": false,
"notNull": true
},
"providerAccountId": {
"name": "providerAccountId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"token_type": {
"name": "token_type",
"type": "text",
"primaryKey": false,
"notNull": false
},
"scope": {
"name": "scope",
"type": "text",
"primaryKey": false,
"notNull": false
},
"id_token": {
"name": "id_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"session_state": {
"name": "session_state",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"account_userId_user_id_fk": {
"name": "account_userId_user_id_fk",
"tableFrom": "account",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {
"account_provider_providerAccountId_pk": {
"name": "account_provider_providerAccountId_pk",
"columns": [
"provider",
"providerAccountId"
]
}
},
"uniqueConstraints": {}
},
"guideFeedback": {
"name": "guideFeedback",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"feedback": {
"name": "feedback",
"type": "text",
"primaryKey": false,
"notNull": true
},
"route": {
"name": "route",
"type": "text",
"primaryKey": false,
"notNull": true
},
"inputText": {
"name": "inputText",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"jobsList": {
"name": "jobsList",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"steps": {
"name": "steps",
"type": "json",
"primaryKey": false,
"notNull": true
},
"sernbinid": {
"name": "sernbinid",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"session": {
"name": "session",
"schema": "",
"columns": {
"sessionToken": {
"name": "sessionToken",
"type": "text",
"primaryKey": true,
"notNull": true
},
"userId": {
"name": "userId",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {
"session_userId_user_id_fk": {
"name": "session_userId_user_id_fk",
"tableFrom": "session",
"tableTo": "user",
"columnsFrom": [
"userId"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"user": {
"name": "user",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": true
},
"emailVerified": {
"name": "emailVerified",
"type": "timestamp",
"primaryKey": false,
"notNull": false
},
"image": {
"name": "image",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"verificationToken": {
"name": "verificationToken",
"schema": "",
"columns": {
"identifier": {
"name": "identifier",
"type": "text",
"primaryKey": false,
"notNull": true
},
"token": {
"name": "token",
"type": "text",
"primaryKey": false,
"notNull": true
},
"expires": {
"name": "expires",
"type": "timestamp",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {
"verificationToken_identifier_token_pk": {
"name": "verificationToken_identifier_token_pk",
"columns": [
"identifier",
"token"
]
}
},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,83 +0,0 @@
{
"id": "85868c6b-5657-45c8-a26c-e17cd20787fb",
"prevId": "63e42e23-78aa-4b67-96a2-9b1bc6bf15c8",
"version": "5",
"dialect": "pg",
"tables": {
"guideFeedback": {
"name": "guideFeedback",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true
},
"feedback": {
"name": "feedback",
"type": "text",
"primaryKey": false,
"notNull": true
},
"route": {
"name": "route",
"type": "text",
"primaryKey": false,
"notNull": true
},
"inputText": {
"name": "inputText",
"type": "text",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
},
"jobsList": {
"name": "jobsList",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "bigserial",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"steps": {
"name": "steps",
"type": "json",
"primaryKey": false,
"notNull": true
},
"sernbinid": {
"name": "sernbinid",
"type": "text",
"primaryKey": false,
"notNull": true
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {}
}
},
"enums": {},
"schemas": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,27 +0,0 @@
{
"version": "5",
"dialect": "pg",
"entries": [
{
"idx": 0,
"version": "5",
"when": 1709242740332,
"tag": "0000_greedy_sandman",
"breakpoints": true
},
{
"idx": 1,
"version": "5",
"when": 1709334685582,
"tag": "0001_burly_carnage",
"breakpoints": true
},
{
"idx": 2,
"version": "5",
"when": 1711311565795,
"tag": "0002_soft_lilith",
"breakpoints": true
}
]
}

View File

@@ -1,26 +0,0 @@
{
"name": "database",
"packageManager": "yarn@4.0.2",
"version": "1.0.0",
"type": "module",
"scripts": {
"dev": "tsc-watch --preserveWatchOutput",
"migrate": "node dist/migrations.js",
"generateMigrations": "drizzle-kit generate:pg --schema ./src/schema.ts",
"deploy": "yarn generateMigrations && yarn migrate",
"build": "tsc"
},
"dependencies": {
"@auth/core": "^0.19.0",
"drizzle-orm": "^0.29.2",
"postgres": "^3.4.3"
},
"devDependencies": {
"@types/pg": "^8.10.9",
"dotenv": "^16.3.1",
"drizzle-kit": "^0.20.8",
"pg": "^8.11.3",
"tsc-watch": "^6.0.4",
"typescript": "^5.3.3"
}
}

View File

@@ -1,9 +0,0 @@
import { drizzle } from "drizzle-orm/postgres-js";
import postgres from "postgres";
import 'dotenv/config'
import * as schema from './schema.js';
const client = postgres(process.env.DATABASE_URL!);
export * as schema from './schema.js';
export default drizzle(client, { schema });

View File

@@ -1,16 +0,0 @@
import { drizzle } from "drizzle-orm/postgres-js/driver";
import { migrate } from "drizzle-orm/postgres-js/migrator";
import postgres from "postgres";
import 'dotenv/config'
// this will automatically run needed migrations on the database
const migrationClient = postgres(process.env.DATABASE_URL!, { max: 1 });
migrate(drizzle(migrationClient), { migrationsFolder: "./drizzle" })
.then(() => {
console.log("Migrations complete!");
process.exit(0);
})
.catch((err) => {
console.error("Migrations failed!", err);
process.exit(1);
});

View File

@@ -1,32 +0,0 @@
import {
timestamp,
pgTable,
text,
primaryKey,
integer,
json,
bigserial
} from "drizzle-orm/pg-core";
import type { AdapterAccount } from "@auth/core/adapters";
// automata schemas
export const guideFeedback = pgTable("guideFeedback", {
id: text("id").notNull().primaryKey(),
feedback: text("feedback").notNull(),
route: text("route").notNull(),
inputText: text("inputText"),
})
export const jobsList = pgTable("jobsList", {
id: bigserial('id', { mode: 'number' }).primaryKey(),
name: text("name").notNull(),
steps: json("steps").notNull(),
sernbinid: text("sernbinid").notNull(),
})
// types
interface JobLog {
timestamp: Date;
message: string;
level: 'info' | 'error';
}

View File

@@ -1,13 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "./src",
},
"include": [
"**/*.ts"
],
"exclude": [
"dist"
]
}

View File

@@ -1,4 +0,0 @@
providers = ["..."]
[phases.setup]
nixPkgs = ["..." , "openssh"]

View File

@@ -1,30 +0,0 @@
{
"name": "sern-automata",
"version": "1.0.0",
"private": true,
"repository": "https://github.com/sern-handler/automata.git",
"author": "Izan Gil <66965250+SrIzan10@users.noreply.github.com>",
"license": "MIT",
"type": "module",
"workspaces": [
"apps/*",
"!repos/*"
],
"scripts": {
"build:api": "yarn workspace api build",
"build:database": "yarn workspace database build",
"start:api": "yarn workspace api start",
"db:deploy": "yarn workspace database deploy",
"dev": "concurrently \"yarn workspace api dev\" \"yarn workspace database dev\"",
"setup": "bash apps/api/util/setup.sh"
},
"//": [
"postgres: \"cd dev/postgresql && docker compose up\""
],
"devDependencies": {
"concurrently": "^8.2.2",
"tsc-node": "^0.0.3",
"typescript": "^5.3.3"
},
"packageManager": "yarn@4.0.2"
}

View File

@@ -1,8 +0,0 @@
Host github.com
HostName ssh.github.com
Port 443
User git
IdentityFile /ssh/github
IdentitiesOnly yes
StrictHostKeyChecking no
UserKnownHostsFile /dev/null

View File

@@ -1,21 +0,0 @@
{
"compilerOptions": {
"target": "ESNext",
"strict": true,
"noUncheckedIndexedAccess": true,
// "lib": ["ES2019", "ES2021.String"],
"esModuleInterop": true,
"allowJs": true,
"allowSyntheticDefaultImports": true,
"moduleResolution": "node",
"module": "ESNext",
"resolveJsonModule": true,
"skipLibCheck": true,
"isolatedModules": true,
"declaration": true,
"paths": {
"@database/*": ["./node_modules/database/src/*"],
}
},
"exclude": []
}

2913
yarn.lock

File diff suppressed because it is too large Load Diff