Move core directory to base and delete Soul Studio directory

This commit is contained in:
Vahid Al
2023-08-25 15:32:10 +03:30
parent 0a41c834de
commit 8cd6c172bd
54 changed files with 128 additions and 1748 deletions

113
.gitignore vendored
View File

@@ -1,3 +1,112 @@
*.db-*
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Sqlite files
*.db
*.db-shm
*.db-wal
*Chinook*
_extensions/
_extensions/

View File

@@ -1,7 +1,7 @@
<p align="center">
<img src='docs/logo.png' height='150px' style="">
<p align="center">
A SQLite REST and Realtime server
A SQLite REST and Realtime server
</p>
</p>
@@ -59,7 +59,7 @@ Soul is able to be extended (e.g. Adding custom APIs) via extensions, you can fi
## Soul Studio
Soul Studio provides a GUI to work with your database.
[Soul Studio](https://github.com/thevahidal/soul-studio) provides a GUI to work with your database.
Right now Soul Studio is in early stages of development and not useful to work with.
@@ -71,26 +71,6 @@ Right now Soul Studio is in early stages of development and not useful to work w
```bash
git clone https://github.com/thevahidal/soul # Clone project
```
### Core API
```bash
cd core # Move into the core directory
cp .env.sample .env # Duplicate sample environment variables
nano .env # Update the environment variables
npm install # Install dependencies
npm run dev # Start the dev server
```
### Studio
Make sure that Soul Core API is up and running and then
```bash
cd studio # Move into the studio directory
cp .env.sample .env # Duplicate sample environment variables
nano .env # Update the environment variables

3
core/.gitignore vendored
View File

@@ -107,3 +107,6 @@ dist
*.db
*.db-shm
*.db-wal
*Chinook*
_extensions/

View File

@@ -19,12 +19,11 @@ soul -d ./Chinook_Sqlite.sqlite -p 8000
<details>
<summary>Or Using Local Development</summary>
```bash
git clone https://github.com/thevahidal/soul # Clone project
cd core/
npm install # Install dependencies
npm link # might need `sudo`
npm link # might need `sudo`
soul -d ./Chinook_Sqlite.sqlite -p 8000
```
</details>
@@ -49,7 +48,7 @@ curl --request POST \
"name": "Artist", # note that we already have an `artists` table
"schema": [
# ...
]
]
}'
```

View File

@@ -25,12 +25,11 @@ soul -d ./Chinook_Sqlite.sqlite -p 8000 -e "/absolute/path/to/_extensions/"
<details>
<summary>Or Using Local Development</summary>
```bash
git clone https://github.com/thevahidal/soul # Clone project
cd core/
npm install # Install dependencies
npm link # might need `sudo`
npm link # might need `sudo`
soul -d ./Chinook_Sqlite.sqlite -p 8000 -e "/absolute/path/to/_extensions/"
```
</details>
@@ -45,7 +44,7 @@ const hello = {
method: 'GET',
path: '/api/hello-soul',
handler: (req, res, db) => {
res.status(200).json({
res.status(200).json({
message: 'Hello Soul!'
});
},
@@ -79,8 +78,8 @@ const searchTables = {
handler: (req, res, db) => {
const { q } = req.query;
const sql = `
SELECT name FROM sqlite_master
WHERE type='table'
SELECT name FROM sqlite_master
WHERE type='table'
AND name LIKE $searchQuery
`;
try {

View File

@@ -27,12 +27,11 @@ soul -d ./Chinook_Sqlite.sqlite -p 8000
<details>
<summary>Or Using Local Development</summary>
```bash
git clone https://github.com/thevahidal/soul # Clone project
cd core/
npm install # Install dependencies
npm link # might need `sudo`
npm link # might need `sudo`
soul -d ./Chinook_Sqlite.sqlite -p 8000
```
</details>

View File

@@ -1,7 +1,7 @@
{
"swagger": "2.0",
"info": {
"version": "0.5.2",
"version": "0.6.1",
"title": "Soul API",
"description": "API Documentation for <b>Soul</b>, a SQLite REST and realtime server. "
},
@@ -755,4 +755,4 @@
"$ref": "#/definitions/Transaction"
}
}
}
}

View File

@@ -1 +0,0 @@
STUDIO_PORT=5000

8
studio/.gitignore vendored
View File

@@ -1,8 +0,0 @@
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.sample

View File

@@ -1 +0,0 @@
engine-strict=true

View File

@@ -1 +0,0 @@
# Soul Studio

1234
studio/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,32 +0,0 @@
{
"name": "soul-studio",
"version": "0.0.2",
"description": "GUI for Soul: A SQLite REST and realtime server",
"scripts": {
"dev": "vite dev --port 3000",
"build": "vite build",
"preview": "vite preview"
},
"repository": {
"type": "git",
"url": "git+https://github.com/thevahidal/soul.git"
},
"author": "Vahid Al @thevahidal",
"license": "MIT",
"bugs": {
"url": "https://github.com/thevahidal/soul/issues"
},
"homepage": "https://github.com/thevahidal/soul#readme",
"devDependencies": {
"@sveltejs/adapter-auto": "2.0.0",
"@sveltejs/adapter-node": "^1.2.0",
"@sveltejs/adapter-static": "^2.0.1",
"@sveltejs/kit": "1.8.5",
"svelte": "^3.55.1",
"vite": "^4.1.4"
},
"type": "module",
"files": [
"build/"
]
}

View File

@@ -1,20 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
<title>Soul Studio</title>
%sveltekit.head%
</head>
<body>
<div>%sveltekit.body%</div>
</body>
<style>
body, html, body > div {
margin: 0;
padding: 0;
}
</style>
</html>

View File

@@ -1,42 +0,0 @@
<script>
import './styles.css';
let styles = {
background: ['#0f0f0f', '#111111', '#292929', '#414141', '#585858'],
paper: '#212121',
text: ['#ffffff', '#fdfdfd', '#e4e4e4', '#cacaca', '#b1b1b1'],
divider: '#222222',
primary: ['#008d53', '#009d5c', '#19a76c', '#33b17d'],
secondary: ['#009cd7', '#00adef', '#19b5f1', '#33bdf2'],
info: ['#dd8317', '#f5911a', '#f69c31', '#f7a748', ],
success: ['#00b028', '#00c42c', '#19ca41', '#33d056', '#4dd66b', '#66dc80'],
warning: ['#e5b800', '#fecc00', '#fed119', '#fed633'],
'warning-darker': ['#cba300', '#b28f00', '#987a00', '#7f6600', '#665200', '#4c3d00'],
danger: '#ff0b4b',
};
$: cssVarStyles = Object.entries(styles)
.map(([key, value]) => {
if (Array.isArray(value)) {
return value.map((v, i) => `--${key}-${i}: ${v};`).join('');
}
return `--${key}: ${value};`;
})
.join(';');
</script>
<div class="wrapper" style={cssVarStyles}>
<slot />
<footer />
</div>
<style>
.wrapper {
background-color: var(--background-1);
min-height: 100vh;
min-width: 100vw;
color: var(--text-1);
}
</style>

View File

@@ -1,325 +0,0 @@
<script>
import { onMount } from 'svelte';
let selectedTab = null;
let tables = [];
let tablesLoading = true;
let rows = [];
let rowsLoading = false;
let columns = [];
let columnsLoading = false;
const ROW_HEIGHT = 35;
let viewportHeight;
let viewportWidth;
let addRecordMode = false;
onMount(async () => {
fetch('http://localhost:8000/api/tables')
.then((response) => response.json())
.then(({ data }) => {
tables = data;
selectedTab = data[0].name;
handleTableTabClick(data[0]?.name);
tablesLoading = false;
})
.catch((error) => {
console.log(error);
return [];
});
});
function handleTableTabClick(tableName) {
rowsLoading = true;
columnsLoading = true;
selectedTab = tableName;
addRecordMode = false
fetch(`http://localhost:8000/api/tables/${tableName}`)
.then((response) => response.json())
.then(({ data }) => {
columns = data;
columnsLoading = false;
})
.catch((error) => {
console.log(error);
return [];
});
fetch(`http://localhost:8000/api/tables/${tableName}/rows`)
.then((response) => response.json())
.then(({ data }) => {
rows = data.map((row) => {
let fields = {};
for (const key in row) {
fields[key] = {
value: row[key],
editable: false,
};
}
return { fields };
});
rowsLoading = false;
})
.catch((error) => {
console.log(error);
return [];
});
}
function handleAddRecord() {
addRecordMode = true;
const newRow = {
fields: {},
new: true,
};
columns.forEach((column) => {
newRow.fields[column.name] = {
value: '',
editable: true,
placeholder: column.dflt_value || column.notnull === 1 ? '' : 'null',
};
});
rows = [newRow, ...rows];
}
</script>
<svelte:window bind:innerHeight={viewportHeight} />
<div class="wrapper">
{#if tablesLoading}
<p>Loading...</p>
{:else}
<ul class="tables">
<li>
<button class="soul"> Soul Studio </button>
</li>
{#each tables as table}
<li>
<button
class:selected={table.name === selectedTab}
on:click={handleTableTabClick(table.name)}
>
{table.name.replace('_', ' ')}
</button>
</li>
{/each}
</ul>
<div class="options">
<button class="button" on:click={handleAddRecord}> Add record </button>
{#if addRecordMode}
<button class="button primary"> Save {rows.reduce((acc, curr) => acc + (curr.new ? 1 : 0), 0)} Changes </button>
<button class="button transparent"> Discard Change </button>
{/if}
</div>
<div class="table-wrapper">
<table cellspacing="0">
<thead>
<tr>
<th class="select">
<input type="checkbox" />
</th>
{#each columns as column}
<th>{column.name}</th>
{/each}
</tr>
</thead>
<tbody>
{#each rows as row}
<tr class:new={row.new} class="table-row">
<td class="select">
<input type="checkbox" />
</td>
{#each Object.keys(row.fields) as key}
<td
class:editing={row.fields[key].editable}
on:dblclick|stopPropagation={() => {
row.fields[key].editable = true
}}
>
{#if !row.fields[key].editable}
<div class="cell">
{row.fields[key].value}
</div>
{:else}
<input
class="cell"
bind:this={row.fields[key].input}
bind:value={row.fields[key].value}
on:blur={() => {
if (row.new) return
row.fields[key].editable = false
}}
placeholder={row.fields[key].placeholder}
/>
{/if}
</td>
{/each}
</tr>
{/each}
</tbody>
</table>
<div class="phantom">
{#each new Array(Math.max(Math.floor(viewportHeight / ROW_HEIGHT) - 5, 5)).fill(0) as row}
<div class="row" />
{/each}
</div>
</div>
{/if}
</div>
<style>
ul.tables {
margin: 0;
list-style: none;
padding: 0;
display: flex;
background-color: var(--background-1);
border-bottom: 1px solid var(--divider);
max-width: 100vw;
overflow-x: scroll;
}
ul.tables li button {
text-transform: capitalize;
font-weight: bold;
font-size: 14px;
border: none;
background: none;
color: var(--text-1);
padding: 0 2rem;
height: 35px;
border-right: 1px solid var(--divider);
transition: 0.3s all;
}
ul.tables li button:hover {
background: var(--background-3);
}
.soul {
background-color: var(--primary-0) !important;
}
ul.tables li button.selected {
background: var(--background-2);
}
.options {
padding: 1rem;
display: flex;
}
thead {
background-color: var(--background-2);
}
.button {
border: none;
background: var(--background-2);
font-weight: bold;
padding: 0 1rem;
height: 30px;
color: var(--text-1);
border-radius: 5px;
margin: 0 0.5rem;
transition: 0.5s all;
}
.button:hover {
background: var(--background-3);
}
.button.primary {
background: var(--primary-0);
}
.button.primary:hover {
background: var(--primary-1);
}
.button.transparent {
background: none;
color: var(--text-2);
margin: 0;
}
.button.transparent:hover {
color: var(--text-3);
}
td,
th {
min-width: 200px;
text-align: left;
font-size: 14px;
height: 35px;
margin: 0;
border-right: 1px solid var(--divider);
border-bottom: 1px solid var(--divider);
padding: 0 1rem;
}
th {
padding: 0 1rem;
}
td .cell {
background-color: transparent;
border: none !important;
padding: 0 !important;
color: var(--text-1);
max-width: 200px;
margin: 0;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
td input.cell {
height: 100%;
}
td.editing {
}
th {
border-top: 1px solid var(--divider);
}
.new {
background-color: var(--warning-darker-5);
}
.new:hover {
background-color: var(--warning-darker-5) !important;
}
th.select,
td.select {
min-width: unset !important;
}
.table-row:hover {
background: var(--background-2);
transition: 0.3s all;
}
.table-wrapper {
position: relative;
}
table {
z-index: 100;
position: relative;
}
.phantom {
position: absolute;
top: 0;
z-index: 0;
}
.phantom .row {
height: 35px;
min-width: 100vw;
border-bottom: 1px solid var(--divider);
}
.phantom .row:first-child {
border-top: 1px solid var(--divider);
background-color: var(--background-2);
}
</style>

View File

@@ -1,23 +0,0 @@
:root {
}
body > div {
display: flex;
flex-direction: column;
flex-wrap: wrap;
}
* {
font-family: 'Courier New', Courier, monospace !important;
}
body::-webkit-scrollbar {
width: 1em;
}
body::-webkit-scrollbar-track {
box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);
}
body::-webkit-scrollbar-thumb {
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,15 +0,0 @@
import adapter from '@sveltejs/adapter-node';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter({
envPrefix: "STUDIO_",
}),
paths: {
base: "/studio",
}
},
};
export default config;

View File

@@ -1,7 +0,0 @@
import { sveltekit } from '@sveltejs/kit/vite';
const config = {
plugins: [sveltekit()]
};
export default config;