mirror of
https://github.com/sern-handler/automata
synced 2026-06-06 01:16:51 +00:00
chore: everything gone
This commit is contained in:
@@ -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
15
.gitignore
vendored
@@ -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.*
|
||||
5
.vscode/extensions.json
vendored
5
.vscode/extensions.json
vendored
@@ -1,5 +0,0 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"arcanis.vscode-zipfs"
|
||||
]
|
||||
}
|
||||
9
.vscode/settings.json
vendored
9
.vscode/settings.json
vendored
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"dotenv.enableAutocloaking": false,
|
||||
"search.exclude": {
|
||||
"**/.yarn": true,
|
||||
"**/.pnp.*": true
|
||||
},
|
||||
"typescript.tsdk": ".yarn/sdks/typescript/lib",
|
||||
"typescript.enablePromptUseWorkspaceTsdk": true
|
||||
}
|
||||
893
.yarn/releases/yarn-4.0.2.cjs
vendored
893
.yarn/releases/yarn-4.0.2.cjs
vendored
File diff suppressed because one or more lines are too long
5
.yarn/sdks/integrations.yml
vendored
5
.yarn/sdks/integrations.yml
vendored
@@ -1,5 +0,0 @@
|
||||
# This file is automatically generated by @yarnpkg/sdks.
|
||||
# Manual changes might be lost!
|
||||
|
||||
integrations:
|
||||
- vscode
|
||||
20
.yarn/sdks/typescript/bin/tsc
vendored
20
.yarn/sdks/typescript/bin/tsc
vendored
@@ -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`);
|
||||
20
.yarn/sdks/typescript/bin/tsserver
vendored
20
.yarn/sdks/typescript/bin/tsserver
vendored
@@ -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`);
|
||||
20
.yarn/sdks/typescript/lib/tsc.js
vendored
20
.yarn/sdks/typescript/lib/tsc.js
vendored
@@ -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`);
|
||||
225
.yarn/sdks/typescript/lib/tsserver.js
vendored
225
.yarn/sdks/typescript/lib/tsserver.js
vendored
@@ -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`));
|
||||
225
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
225
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
@@ -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`));
|
||||
20
.yarn/sdks/typescript/lib/typescript.js
vendored
20
.yarn/sdks/typescript/lib/typescript.js
vendored
@@ -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`);
|
||||
10
.yarn/sdks/typescript/package.json
vendored
10
.yarn/sdks/typescript/package.json
vendored
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"name": "typescript",
|
||||
"version": "5.3.3-sdk",
|
||||
"main": "./lib/typescript.js",
|
||||
"type": "commonjs",
|
||||
"bin": {
|
||||
"tsc": "./bin/tsc",
|
||||
"tsserver": "./bin/tsserver"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
18
README.md
18
README.md
@@ -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`).
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"tabWidth": 4,
|
||||
"useTabs": true
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -1,3 +0,0 @@
|
||||
[
|
||||
{ "file": "pst.clj", "route": "/bb/getPstTime", "method": "GET" }
|
||||
]
|
||||
@@ -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}`)
|
||||
})
|
||||
119
apps/api/jobs.ts
119
apps/api/jobs.ts
@@ -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[];
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
|
||||
@@ -1 +0,0 @@
|
||||
echo "hi"
|
||||
@@ -1,3 +0,0 @@
|
||||
RANDOMVARIABLE=$(echo $NT_ARGS | jq -r '.randomVariable')
|
||||
|
||||
echo $RANDOMVARIABLE
|
||||
@@ -1 +0,0 @@
|
||||
yarn build
|
||||
@@ -1,2 +0,0 @@
|
||||
mv ./docusaurus.config.js ./original.docusaurus.config.js
|
||||
mv ./docgen.docusaurus.config.js ./docusaurus.config.js
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,2 +0,0 @@
|
||||
mv docusaurus.config.js docgen.docusaurus.config.js
|
||||
mv original.docusaurus.config.js docusaurus.config.js
|
||||
@@ -1 +0,0 @@
|
||||
yarn typedoc-json
|
||||
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": ".",
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"repos",
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
@@ -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\`\`\``;
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 ..
|
||||
@@ -1 +0,0 @@
|
||||
export const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||
@@ -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';
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
# database
|
||||
@@ -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 $$;
|
||||
@@ -1 +0,0 @@
|
||||
ALTER TABLE "jobsList" ADD COLUMN "sernbinid" text NOT NULL;
|
||||
@@ -1,4 +0,0 @@
|
||||
DROP TABLE "account";--> statement-breakpoint
|
||||
DROP TABLE "session";--> statement-breakpoint
|
||||
DROP TABLE "user";--> statement-breakpoint
|
||||
DROP TABLE "verificationToken";
|
||||
@@ -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": {}
|
||||
}
|
||||
}
|
||||
@@ -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": {}
|
||||
}
|
||||
}
|
||||
@@ -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": {}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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 });
|
||||
@@ -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);
|
||||
});
|
||||
@@ -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';
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "./src",
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"dist"
|
||||
]
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
providers = ["..."]
|
||||
|
||||
[phases.setup]
|
||||
nixPkgs = ["..." , "openssh"]
|
||||
30
package.json
30
package.json
@@ -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"
|
||||
}
|
||||
8
ssh.conf
8
ssh.conf
@@ -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
|
||||
@@ -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": []
|
||||
}
|
||||
Reference in New Issue
Block a user