This commit is contained in:
parent
589a9ce2fe
commit
1550d77ca6
33 changed files with 3165 additions and 11259 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -4,3 +4,4 @@ node_modules
|
||||||
.env
|
.env
|
||||||
/generated
|
/generated
|
||||||
/result*
|
/result*
|
||||||
|
.solid
|
||||||
|
|
30
README.md
Normal file
30
README.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
# SolidStart
|
||||||
|
|
||||||
|
Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com);
|
||||||
|
|
||||||
|
## Creating a project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# create a new project in the current directory
|
||||||
|
npm init solid@latest
|
||||||
|
|
||||||
|
# create a new project in my-app
|
||||||
|
npm init solid@latest my-app
|
||||||
|
```
|
||||||
|
|
||||||
|
## Developing
|
||||||
|
|
||||||
|
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# or start the server and open the app in a new browser tab
|
||||||
|
npm run dev -- --open
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building
|
||||||
|
|
||||||
|
Solid apps are built with _adapters_, which optimise your project for deployment to different environments.
|
||||||
|
|
||||||
|
By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different adapter, add it to the `devDependencies` in `package.json` and specify in your `vite.config.js`.
|
|
@ -1,87 +0,0 @@
|
||||||
# Index
|
|
||||||
|
|
||||||
## Docs
|
|
||||||
- [docs/book.toml](docs/book.toml)
|
|
||||||
- [docs/make-then-tera.sh](docs/make-then-tera.sh)
|
|
||||||
|
|
||||||
### Book
|
|
||||||
- [docs/book/404.html](docs/book/404.html)
|
|
||||||
- [docs/book/ayu-highlight.css](docs/book/ayu-highlight.css)
|
|
||||||
- [docs/book/book.js](docs/book/book.js)
|
|
||||||
- [docs/book/clipboard.min.js](docs/book/clipboard.min.js)
|
|
||||||
- [docs/book/elasticlunr.min.js](docs/book/elasticlunr.min.js)
|
|
||||||
- [docs/book/favicon.png](docs/book/favicon.png)
|
|
||||||
- [docs/book/favicon.svg](docs/book/favicon.svg)
|
|
||||||
- [docs/book/highlight.css](docs/book/highlight.css)
|
|
||||||
- [docs/book/highlight.js](docs/book/highlight.js)
|
|
||||||
- [docs/book/index.html](docs/book/index.html)
|
|
||||||
- [docs/book/mark.min.js](docs/book/mark.min.js)
|
|
||||||
- [docs/book/print.html](docs/book/print.html)
|
|
||||||
- [docs/book/searcher.js](docs/book/searcher.js)
|
|
||||||
- [docs/book/searchindex.js](docs/book/searchindex.js)
|
|
||||||
- [docs/book/searchindex.json](docs/book/searchindex.json)
|
|
||||||
- [docs/book/tomorrow-night.css](docs/book/tomorrow-night.css)
|
|
||||||
|
|
||||||
### Src
|
|
||||||
- [docs/src/SUMMARY](docs/src/SUMMARY.md)
|
|
||||||
|
|
||||||
### Book
|
|
||||||
|
|
||||||
#### App
|
|
||||||
- [docs/book/app/sync.html](docs/book/app/sync.html)
|
|
||||||
|
|
||||||
#### Css
|
|
||||||
- [docs/book/css/chrome.css](docs/book/css/chrome.css)
|
|
||||||
- [docs/book/css/general.css](docs/book/css/general.css)
|
|
||||||
- [docs/book/css/print.css](docs/book/css/print.css)
|
|
||||||
- [docs/book/css/variables.css](docs/book/css/variables.css)
|
|
||||||
|
|
||||||
#### Dev
|
|
||||||
- [docs/book/dev/api.html](docs/book/dev/api.html)
|
|
||||||
- [docs/book/dev/meta_json.html](docs/book/dev/meta_json.html)
|
|
||||||
|
|
||||||
#### Lib
|
|
||||||
- [docs/book/lib/api_reference.html](docs/book/lib/api_reference.html)
|
|
||||||
|
|
||||||
#### Fonts
|
|
||||||
- [docs/book/fonts/OPEN-SANS-LICENSE.txt](docs/book/fonts/OPEN-SANS-LICENSE.txt)
|
|
||||||
- [docs/book/fonts/SOURCE-CODE-PRO-LICENSE.txt](docs/book/fonts/SOURCE-CODE-PRO-LICENSE.txt)
|
|
||||||
- [docs/book/fonts/fonts.css](docs/book/fonts/fonts.css)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-300.woff2](docs/book/fonts/open-sans-v17-all-charsets-300.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-300italic.woff2](docs/book/fonts/open-sans-v17-all-charsets-300italic.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-600.woff2](docs/book/fonts/open-sans-v17-all-charsets-600.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-600italic.woff2](docs/book/fonts/open-sans-v17-all-charsets-600italic.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-700.woff2](docs/book/fonts/open-sans-v17-all-charsets-700.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-700italic.woff2](docs/book/fonts/open-sans-v17-all-charsets-700italic.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-800.woff2](docs/book/fonts/open-sans-v17-all-charsets-800.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-800italic.woff2](docs/book/fonts/open-sans-v17-all-charsets-800italic.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-italic.woff2](docs/book/fonts/open-sans-v17-all-charsets-italic.woff2)
|
|
||||||
- [docs/book/fonts/open-sans-v17-all-charsets-regular.woff2](docs/book/fonts/open-sans-v17-all-charsets-regular.woff2)
|
|
||||||
- [docs/book/fonts/source-code-pro-v11-all-charsets-500.woff2](docs/book/fonts/source-code-pro-v11-all-charsets-500.woff2)
|
|
||||||
|
|
||||||
### Src
|
|
||||||
|
|
||||||
#### App
|
|
||||||
- [docs/src/app/sync](docs/src/app/sync.md)
|
|
||||||
|
|
||||||
#### Dev
|
|
||||||
- [docs/src/dev/api](docs/src/dev/api.md)
|
|
||||||
- [docs/src/dev/meta_json](docs/src/dev/meta_json.md)
|
|
||||||
|
|
||||||
#### Lib
|
|
||||||
- [docs/src/lib/api_reference](docs/src/lib/api_reference.md)
|
|
||||||
|
|
||||||
### Book
|
|
||||||
|
|
||||||
#### FontAwesome
|
|
||||||
|
|
||||||
##### Css
|
|
||||||
- [docs/book/FontAwesome/css/font-awesome.css](docs/book/FontAwesome/css/font-awesome.css)
|
|
||||||
|
|
||||||
##### Fonts
|
|
||||||
- [docs/book/FontAwesome/fonts/FontAwesome.ttf](docs/book/FontAwesome/fonts/FontAwesome.ttf)
|
|
||||||
- [docs/book/FontAwesome/fonts/fontawesome-webfont.eot](docs/book/FontAwesome/fonts/fontawesome-webfont.eot)
|
|
||||||
- [docs/book/FontAwesome/fonts/fontawesome-webfont.svg](docs/book/FontAwesome/fonts/fontawesome-webfont.svg)
|
|
||||||
- [docs/book/FontAwesome/fonts/fontawesome-webfont.ttf](docs/book/FontAwesome/fonts/fontawesome-webfont.ttf)
|
|
||||||
- [docs/book/FontAwesome/fonts/fontawesome-webfont.woff](docs/book/FontAwesome/fonts/fontawesome-webfont.woff)
|
|
||||||
- [docs/book/FontAwesome/fonts/fontawesome-webfont.woff2](docs/book/FontAwesome/fonts/fontawesome-webfont.woff2)
|
|
|
@ -1,7 +1,7 @@
|
||||||
- CLI API
|
- CLI API
|
||||||
|
|
||||||
- `mznotes install` : Install a script into the database
|
- `panorama install` : Install a script into the database
|
||||||
- `mznotes show` : Show the information about a particular node, by ID
|
- `panorama show` : Show the information about a particular node, by ID
|
||||||
|
|
||||||
- Database of nodes + code
|
- Database of nodes + code
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@
|
||||||
|
|
||||||
- Interfaces:
|
- Interfaces:
|
||||||
|
|
||||||
-
|
- `addTodo()`
|
||||||
|
|
||||||
- Content / blob storage
|
- Content / blob storage
|
||||||
|
|
||||||
|
@ -137,3 +137,5 @@
|
||||||
- Have the frontend also shipped with the backend?
|
- Have the frontend also shipped with the backend?
|
||||||
|
|
||||||
- Subset of React components to typecheck against
|
- Subset of React components to typecheck against
|
||||||
|
|
||||||
|
- Aggregated queries and group by? Joins?
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
cargo-expand
|
cargo-expand
|
||||||
cargo-flamegraph
|
cargo-flamegraph
|
||||||
cargo-watch
|
cargo-watch
|
||||||
|
sqlite
|
||||||
|
|
||||||
zlib
|
zlib
|
||||||
|
|
||||||
|
|
13563
package-lock.json
generated
13563
package-lock.json
generated
File diff suppressed because it is too large
Load diff
40
package.json
40
package.json
|
@ -1,30 +1,26 @@
|
||||||
{
|
{
|
||||||
"name": "my-prisma-project",
|
"name": "ouais",
|
||||||
"version": "1.0.0",
|
|
||||||
"description": "",
|
|
||||||
"main": "index.js",
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite"
|
"dev": "solid-start dev",
|
||||||
|
"build": "solid-start build",
|
||||||
|
"start": "solid-start start"
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"type": "module",
|
||||||
"author": "",
|
|
||||||
"license": "ISC",
|
|
||||||
"types": "./src/api.d.ts",
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/express": "^4.17.17",
|
"solid-start-node": "^0.2.19",
|
||||||
"json-schema-static-docs": "^0.23.0",
|
"typescript": "^4.9.4",
|
||||||
"nativescript": "^8.5.1",
|
"vite": "^4.1.4"
|
||||||
"prisma": "^4.12.0",
|
|
||||||
"ts-node": "^10.9.1",
|
|
||||||
"typescript": "^5.0.2",
|
|
||||||
"vite": "^4.2.1",
|
|
||||||
"vite-plugin-solid": "^2.6.1",
|
|
||||||
"wetzel": "^0.2.3"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^4.11.0",
|
"@prisma/client": "^4.9.0",
|
||||||
"express": "^4.18.2",
|
"@solidjs/meta": "^0.28.2",
|
||||||
"solid-js": "^1.6.15",
|
"@solidjs/router": "^0.8.2",
|
||||||
"vm2": "^3.9.14"
|
"prisma": "^4.9.0",
|
||||||
|
"solid-js": "^1.7.2",
|
||||||
|
"solid-start": "^0.2.26",
|
||||||
|
"undici": "^5.15.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -4,35 +4,32 @@ CREATE TABLE "Node" (
|
||||||
"label" TEXT
|
"label" TEXT
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateTable
|
|
||||||
CREATE TABLE "Edge" (
|
|
||||||
"id" TEXT NOT NULL PRIMARY KEY
|
|
||||||
);
|
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "Interface" (
|
CREATE TABLE "Interface" (
|
||||||
"id" TEXT NOT NULL PRIMARY KEY
|
"id" TEXT NOT NULL PRIMARY KEY
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "Graph" (
|
CREATE TABLE "Edge" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
"label" TEXT,
|
"label" TEXT,
|
||||||
|
"appId" TEXT NOT NULL,
|
||||||
|
"appKey" TEXT NOT NULL,
|
||||||
"fromId" TEXT NOT NULL,
|
"fromId" TEXT NOT NULL,
|
||||||
"toId" TEXT NOT NULL,
|
"toId" TEXT NOT NULL,
|
||||||
|
CONSTRAINT "Edge_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||||
PRIMARY KEY ("fromId", "toId"),
|
CONSTRAINT "Edge_fromId_fkey" FOREIGN KEY ("fromId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||||
CONSTRAINT "Graph_fromId_fkey" FOREIGN KEY ("fromId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
CONSTRAINT "Edge_toId_fkey" FOREIGN KEY ("toId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
CONSTRAINT "Graph_toId_fkey" FOREIGN KEY ("toId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
|
||||||
);
|
);
|
||||||
|
|
||||||
-- CreateTable
|
-- CreateTable
|
||||||
CREATE TABLE "NodeMeta" (
|
CREATE TABLE "NodeMeta" (
|
||||||
"nodeId" TEXT NOT NULL,
|
"nodeId" TEXT NOT NULL,
|
||||||
"appId" TEXT NOT NULL,
|
"appId" TEXT NOT NULL,
|
||||||
"key" TEXT NOT NULL,
|
"appKey" TEXT NOT NULL,
|
||||||
"value" BLOB NOT NULL,
|
"value" BLOB NOT NULL,
|
||||||
|
|
||||||
PRIMARY KEY ("nodeId", "appId", "key"),
|
PRIMARY KEY ("nodeId", "appId", "appKey"),
|
||||||
CONSTRAINT "NodeMeta_nodeId_fkey" FOREIGN KEY ("nodeId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
CONSTRAINT "NodeMeta_nodeId_fkey" FOREIGN KEY ("nodeId") REFERENCES "Node" ("id") ON DELETE RESTRICT ON UPDATE CASCADE,
|
||||||
CONSTRAINT "NodeMeta_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
CONSTRAINT "NodeMeta_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
);
|
);
|
||||||
|
@ -59,10 +56,20 @@ CREATE TABLE "App" (
|
||||||
CREATE TABLE "Patterns" (
|
CREATE TABLE "Patterns" (
|
||||||
"id" TEXT NOT NULL PRIMARY KEY,
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
"pattern" TEXT NOT NULL,
|
"pattern" TEXT NOT NULL,
|
||||||
|
"type" TEXT NOT NULL,
|
||||||
"appId" TEXT NOT NULL,
|
"appId" TEXT NOT NULL,
|
||||||
"functionName" TEXT NOT NULL,
|
"functionName" TEXT NOT NULL,
|
||||||
CONSTRAINT "Patterns_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
CONSTRAINT "Patterns_appId_fkey" FOREIGN KEY ("appId") REFERENCES "App" ("id") ON DELETE RESTRICT ON UPDATE CASCADE
|
||||||
);
|
);
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "Edge_appId_appKey_idx" ON "Edge"("appId", "appKey");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE UNIQUE INDEX "Edge_fromId_toId_key" ON "Edge"("fromId", "toId");
|
||||||
|
|
||||||
|
-- CreateIndex
|
||||||
|
CREATE INDEX "NodeMeta_appId_appKey_idx" ON "NodeMeta"("appId", "appKey");
|
||||||
|
|
||||||
-- CreateIndex
|
-- CreateIndex
|
||||||
CREATE UNIQUE INDEX "App_localName_key" ON "App"("localName");
|
CREATE UNIQUE INDEX "App_localName_key" ON "App"("localName");
|
|
@ -0,0 +1,14 @@
|
||||||
|
-- RedefineTables
|
||||||
|
PRAGMA foreign_keys=OFF;
|
||||||
|
CREATE TABLE "new_App" (
|
||||||
|
"id" TEXT NOT NULL PRIMARY KEY,
|
||||||
|
"localName" TEXT NOT NULL,
|
||||||
|
"title" TEXT NOT NULL,
|
||||||
|
"installed" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
INSERT INTO "new_App" ("id", "installed", "localName", "title") SELECT "id", "installed", "localName", "title" FROM "App";
|
||||||
|
DROP TABLE "App";
|
||||||
|
ALTER TABLE "new_App" RENAME TO "App";
|
||||||
|
CREATE UNIQUE INDEX "App_localName_key" ON "App"("localName");
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
PRAGMA foreign_keys=ON;
|
|
@ -76,7 +76,7 @@ model App {
|
||||||
localName String @unique
|
localName String @unique
|
||||||
title String
|
title String
|
||||||
|
|
||||||
installed DateTime
|
installed DateTime @default(now())
|
||||||
|
|
||||||
patterns Patterns[]
|
patterns Patterns[]
|
||||||
metaKeys NodeMeta[]
|
metaKeys NodeMeta[]
|
||||||
|
|
BIN
public/favicon.ico
Normal file
BIN
public/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 664 B |
|
@ -1,24 +0,0 @@
|
||||||
import Todos from "./Todos";
|
|
||||||
|
|
||||||
function App() {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<header>
|
|
||||||
<p>
|
|
||||||
Edit <code>src/App.jsx</code> and save to reload.
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
href="https://github.com/solidjs/solid"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
>
|
|
||||||
Learn Solid
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<Todos />
|
|
||||||
</header>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { render } from "solid-js/web";
|
|
||||||
import App from "./App";
|
|
||||||
|
|
||||||
const root = document.getElementById("root");
|
|
||||||
|
|
||||||
if (import.meta.env.DEV && !(root instanceof HTMLElement)) {
|
|
||||||
throw new Error(
|
|
||||||
"Root element not found. Did you forget to add it to your index.html? Or maybe the id attribute got mispelled?"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render(() => <App />, root);
|
|
|
@ -1 +0,0 @@
|
||||||
import Database from "./db";
|
|
|
@ -1,32 +1,38 @@
|
||||||
import { Node, PrismaClient } from "@prisma/client";
|
import { Node, App, PrismaClient } from "@prisma/client";
|
||||||
|
import {
|
||||||
interface ICreateNodeRequest {
|
ICreateNodeRequest,
|
||||||
/**
|
IGetNodeRequest,
|
||||||
* A label for humans. This is not used by the database in any way, it's just
|
IRegisterAppRequest,
|
||||||
* something to print when debugging.
|
} from "./types";
|
||||||
*/
|
|
||||||
label: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A mapping from labels to node creation requests.
|
|
||||||
*/
|
|
||||||
other_nodes: Map<string, ICreateNodeRequest>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A set of edges, using the IDs in auxiliary_nodes.
|
|
||||||
*/
|
|
||||||
edges: Set<ICreateEdgeRequest>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ICreateEdgeRequest {
|
|
||||||
label: string;
|
|
||||||
from_node: string;
|
|
||||||
to_node: string;
|
|
||||||
metadata: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
export default class Database {
|
export default class Database {
|
||||||
public static async createNode(request: ICreateNodeRequest): Promise<Node> {
|
private prisma: PrismaClient;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.prisma = new PrismaClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async registerApp(request: IRegisterAppRequest): Promise<App> {
|
||||||
|
// TODO: Some kind of authentication maybe?
|
||||||
|
|
||||||
|
const app = await this.prisma.app.upsert({
|
||||||
|
where: { localName: request.name },
|
||||||
|
create: { localName: request.name, title: request.name },
|
||||||
|
update: { title: request.name },
|
||||||
|
});
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getNode(request: IGetNodeRequest): Promise<Node | null> {
|
||||||
|
// TODO: Apply filters
|
||||||
|
|
||||||
|
const node = this.prisma.node.findFirst();
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async createNode(request: ICreateNodeRequest): Promise<Node> {
|
||||||
// TODO: Calculate the interfaces that must be implemented
|
// TODO: Calculate the interfaces that must be implemented
|
||||||
// - Use the interface application rules
|
// - Use the interface application rules
|
||||||
// - Insert them into the database
|
// - Insert them into the database
|
||||||
|
@ -41,13 +47,25 @@ export default class Database {
|
||||||
|
|
||||||
// TODO: Run all validations on all of the nodes
|
// TODO: Run all validations on all of the nodes
|
||||||
|
|
||||||
const prisma = new PrismaClient();
|
return await this.prisma.$transaction(async (client) => {
|
||||||
|
const createdNode = await client.node.create({
|
||||||
return await prisma.$transaction(async (client) => {
|
|
||||||
const createdNode = client.node.create({
|
|
||||||
data: { label: request.label },
|
data: { label: request.label },
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (request.metadata_keys) {
|
||||||
|
for (const [key, value] of request.metadata_keys.entries()) {
|
||||||
|
const meta = await client.nodeMeta.create({
|
||||||
|
data: {
|
||||||
|
appKey: key.appKey,
|
||||||
|
appId: key.appId,
|
||||||
|
nodeId: createdNode.id,
|
||||||
|
value: Buffer.from(value),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
console.log("Creating metadata keys", key, value, meta);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return createdNode;
|
return createdNode;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
import {VM} from "vm2";
|
|
||||||
|
|
||||||
export default class Executor {
|
|
||||||
}
|
|
42
src/core/types.ts
Normal file
42
src/core/types.ts
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
export interface IRegisterAppRequest {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMetaKey {
|
||||||
|
appId: string;
|
||||||
|
appKey: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IGetNodeRequest {
|
||||||
|
node_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICreateNodeRequest {
|
||||||
|
/**
|
||||||
|
* A label for humans. This is not used by the database in any way, it's just
|
||||||
|
* something to print when debugging.
|
||||||
|
*/
|
||||||
|
label: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A mapping from labels to node creation requests.
|
||||||
|
*/
|
||||||
|
other_nodes?: Map<string, ICreateNodeRequest>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of edges, using the IDs in auxiliary_nodes.
|
||||||
|
*/
|
||||||
|
edges?: Set<ICreateEdgeRequest>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of metadata keys to values
|
||||||
|
*/
|
||||||
|
metadata_keys?: Map<IMetaKey, string>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICreateEdgeRequest {
|
||||||
|
label: string;
|
||||||
|
from_node: string;
|
||||||
|
to_node: string;
|
||||||
|
metadata: unknown;
|
||||||
|
}
|
10
src/db/index.ts
Normal file
10
src/db/index.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// import { PrismaClient } from "@prisma/client";
|
||||||
|
// export const db = new PrismaClient();
|
||||||
|
|
||||||
|
import Database from "~/core/db";
|
||||||
|
|
||||||
|
export const db = new Database();
|
||||||
|
|
||||||
|
export const todosApp = await db.registerApp({
|
||||||
|
name: "todos",
|
||||||
|
});
|
95
src/db/session.tsx
Normal file
95
src/db/session.tsx
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
import { redirect } from "solid-start/server";
|
||||||
|
import { createCookieSessionStorage } from "solid-start/session";
|
||||||
|
import { db } from ".";
|
||||||
|
type LoginForm = {
|
||||||
|
username: string;
|
||||||
|
password: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function register({ username, password }: LoginForm) {
|
||||||
|
return db.user.create({
|
||||||
|
data: { username: username, password },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function login({ username, password }: LoginForm) {
|
||||||
|
const user = await db.user.findUnique({ where: { username } });
|
||||||
|
if (!user) return null;
|
||||||
|
const isCorrectPassword = password === user.password;
|
||||||
|
if (!isCorrectPassword) return null;
|
||||||
|
return user;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionSecret = import.meta.env.SESSION_SECRET;
|
||||||
|
|
||||||
|
const storage = createCookieSessionStorage({
|
||||||
|
cookie: {
|
||||||
|
name: "RJ_session",
|
||||||
|
// secure doesn't work on localhost for Safari
|
||||||
|
// https://web.dev/when-to-use-local-https/
|
||||||
|
secure: true,
|
||||||
|
secrets: ["hello"],
|
||||||
|
sameSite: "lax",
|
||||||
|
path: "/",
|
||||||
|
maxAge: 60 * 60 * 24 * 30,
|
||||||
|
httpOnly: true,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export function getUserSession(request: Request) {
|
||||||
|
return storage.getSession(request.headers.get("Cookie"));
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUserId(request: Request) {
|
||||||
|
const session = await getUserSession(request);
|
||||||
|
const userId = session.get("userId");
|
||||||
|
if (!userId || typeof userId !== "string") return null;
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function requireUserId(
|
||||||
|
request: Request,
|
||||||
|
redirectTo: string = new URL(request.url).pathname
|
||||||
|
) {
|
||||||
|
const session = await getUserSession(request);
|
||||||
|
const userId = session.get("userId");
|
||||||
|
if (!userId || typeof userId !== "string") {
|
||||||
|
const searchParams = new URLSearchParams([["redirectTo", redirectTo]]);
|
||||||
|
throw redirect(`/login?${searchParams}`);
|
||||||
|
}
|
||||||
|
return userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUser(db: PrismaClient, request: Request) {
|
||||||
|
const userId = await getUserId(request);
|
||||||
|
if (typeof userId !== "string") {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const user = await db.user.findUnique({ where: { id: userId } });
|
||||||
|
return user;
|
||||||
|
} catch {
|
||||||
|
throw logout(request);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function logout(request: Request) {
|
||||||
|
const session = await storage.getSession(request.headers.get("Cookie"));
|
||||||
|
return redirect("/login", {
|
||||||
|
headers: {
|
||||||
|
"Set-Cookie": await storage.destroySession(session),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function createUserSession(userId: string, redirectTo: string) {
|
||||||
|
const session = await storage.getSession();
|
||||||
|
session.set("userId", userId);
|
||||||
|
return redirect(redirectTo, {
|
||||||
|
headers: {
|
||||||
|
"Set-Cookie": await storage.commitSession(session),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
15
src/db/useUser.tsx
Normal file
15
src/db/useUser.tsx
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
import { PrismaClient } from "@prisma/client";
|
||||||
|
import { createServerData$, redirect } from "solid-start/server";
|
||||||
|
import { getUser } from "./session";
|
||||||
|
|
||||||
|
export const useUser = () =>
|
||||||
|
createServerData$(async (_, { request }) => {
|
||||||
|
const db = new PrismaClient();
|
||||||
|
const user = await getUser(db, request);
|
||||||
|
|
||||||
|
if (!user) {
|
||||||
|
throw redirect("/login");
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
|
});
|
3
src/entry-client.tsx
Normal file
3
src/entry-client.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
import { mount, StartClient } from "solid-start/entry-client";
|
||||||
|
|
||||||
|
mount(() => <StartClient />, document);
|
9
src/entry-server.tsx
Normal file
9
src/entry-server.tsx
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import {
|
||||||
|
StartServer,
|
||||||
|
createHandler,
|
||||||
|
renderAsync,
|
||||||
|
} from "solid-start/entry-server";
|
||||||
|
|
||||||
|
export default createHandler(
|
||||||
|
renderAsync((event) => <StartServer event={event} />)
|
||||||
|
);
|
4
src/root.css
Normal file
4
src/root.css
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
body {
|
||||||
|
font-family: Gordita, Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans",
|
||||||
|
"Helvetica Neue", sans-serif;
|
||||||
|
}
|
36
src/root.tsx
Normal file
36
src/root.tsx
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
// @refresh reload
|
||||||
|
import { Suspense } from "solid-js";
|
||||||
|
import {
|
||||||
|
Body,
|
||||||
|
ErrorBoundary,
|
||||||
|
FileRoutes,
|
||||||
|
Head,
|
||||||
|
Html,
|
||||||
|
Meta,
|
||||||
|
Routes,
|
||||||
|
Scripts,
|
||||||
|
Title,
|
||||||
|
} from "solid-start";
|
||||||
|
import "./root.css";
|
||||||
|
|
||||||
|
export default function Root() {
|
||||||
|
return (
|
||||||
|
<Html lang="en">
|
||||||
|
<Head>
|
||||||
|
<Title>SolidStart - With Auth</Title>
|
||||||
|
<Meta charset="utf-8" />
|
||||||
|
<Meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
</Head>
|
||||||
|
<Body>
|
||||||
|
<ErrorBoundary>
|
||||||
|
<Suspense fallback={<div>Loading</div>}>
|
||||||
|
<Routes>
|
||||||
|
<FileRoutes />
|
||||||
|
</Routes>
|
||||||
|
</Suspense>
|
||||||
|
</ErrorBoundary>
|
||||||
|
<Scripts />
|
||||||
|
</Body>
|
||||||
|
</Html>
|
||||||
|
);
|
||||||
|
}
|
7
src/routes/[...404].tsx
Normal file
7
src/routes/[...404].tsx
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
export default function NotFound() {
|
||||||
|
return (
|
||||||
|
<main class="full-width">
|
||||||
|
<h1>Page Not Found</h1>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
28
src/routes/index.tsx
Normal file
28
src/routes/index.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { refetchRouteData, useRouteData } from "solid-start";
|
||||||
|
import { createServerAction$ } from "solid-start/server";
|
||||||
|
import { logout } from "~/db/session";
|
||||||
|
import { useUser } from "../db/useUser";
|
||||||
|
|
||||||
|
export function routeData() {
|
||||||
|
return useUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Home() {
|
||||||
|
const user = useRouteData<typeof routeData>();
|
||||||
|
const [, { Form }] = createServerAction$((f: FormData, { request }) =>
|
||||||
|
logout(request)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main class="full-width">
|
||||||
|
<h1>Hello {user()?.username}</h1>
|
||||||
|
<h3>Message board</h3>
|
||||||
|
<button onClick={() => refetchRouteData()}>Refresh</button>
|
||||||
|
<Form>
|
||||||
|
<button name="logout" type="submit">
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</Form>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
136
src/routes/login.tsx
Normal file
136
src/routes/login.tsx
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
import { Show } from "solid-js";
|
||||||
|
import { useParams, useRouteData } from "solid-start";
|
||||||
|
import { FormError } from "solid-start/data";
|
||||||
|
import {
|
||||||
|
createServerAction$,
|
||||||
|
createServerData$,
|
||||||
|
redirect,
|
||||||
|
} from "solid-start/server";
|
||||||
|
import { db } from "~/db";
|
||||||
|
import { createUserSession, getUser, login, register } from "~/db/session";
|
||||||
|
|
||||||
|
function validateUsername(username: unknown) {
|
||||||
|
if (typeof username !== "string" || username.length < 3) {
|
||||||
|
return `Usernames must be at least 3 characters long`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function validatePassword(password: unknown) {
|
||||||
|
if (typeof password !== "string" || password.length < 6) {
|
||||||
|
return `Passwords must be at least 6 characters long`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function routeData() {
|
||||||
|
return createServerData$(async (_, { request }) => {
|
||||||
|
if (await getUser(db, request)) {
|
||||||
|
throw redirect("/");
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Login() {
|
||||||
|
const data = useRouteData<typeof routeData>();
|
||||||
|
const params = useParams();
|
||||||
|
|
||||||
|
const [loggingIn, { Form }] = createServerAction$(async (form: FormData) => {
|
||||||
|
const loginType = form.get("loginType");
|
||||||
|
const username = form.get("username");
|
||||||
|
const password = form.get("password");
|
||||||
|
const redirectTo = form.get("redirectTo") || "/";
|
||||||
|
if (
|
||||||
|
typeof loginType !== "string" ||
|
||||||
|
typeof username !== "string" ||
|
||||||
|
typeof password !== "string" ||
|
||||||
|
typeof redirectTo !== "string"
|
||||||
|
) {
|
||||||
|
throw new FormError(`Form not submitted correctly.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fields = { loginType, username, password };
|
||||||
|
const fieldErrors = {
|
||||||
|
username: validateUsername(username),
|
||||||
|
password: validatePassword(password),
|
||||||
|
};
|
||||||
|
if (Object.values(fieldErrors).some(Boolean)) {
|
||||||
|
throw new FormError("Fields invalid", { fieldErrors, fields });
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (loginType) {
|
||||||
|
case "login": {
|
||||||
|
const user = await login({ username, password });
|
||||||
|
if (!user) {
|
||||||
|
throw new FormError(`Username/Password combination is incorrect`, {
|
||||||
|
fields,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return createUserSession(`${user.id}`, redirectTo);
|
||||||
|
}
|
||||||
|
case "register": {
|
||||||
|
const userExists = await db.user.findUnique({ where: { username } });
|
||||||
|
if (userExists) {
|
||||||
|
throw new FormError(`User with username ${username} already exists`, {
|
||||||
|
fields,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const user = await register({ username, password });
|
||||||
|
if (!user) {
|
||||||
|
throw new FormError(
|
||||||
|
`Something went wrong trying to create a new user.`,
|
||||||
|
{
|
||||||
|
fields,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return createUserSession(`${user.id}`, redirectTo);
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
throw new FormError(`Login type invalid`, { fields });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<main>
|
||||||
|
<h1>Login</h1>
|
||||||
|
<Form>
|
||||||
|
<input
|
||||||
|
type="hidden"
|
||||||
|
name="redirectTo"
|
||||||
|
value={params.redirectTo ?? "/"}
|
||||||
|
/>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Login or Register?</legend>
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="loginType" value="login" checked={true} />{" "}
|
||||||
|
Login
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="loginType" value="register" /> Register
|
||||||
|
</label>
|
||||||
|
</fieldset>
|
||||||
|
<div>
|
||||||
|
<label for="username-input">Username</label>
|
||||||
|
<input name="username" placeholder="kody" />
|
||||||
|
</div>
|
||||||
|
<Show when={loggingIn.error?.fieldErrors?.username}>
|
||||||
|
<p role="alert">{loggingIn.error.fieldErrors.username}</p>
|
||||||
|
</Show>
|
||||||
|
<div>
|
||||||
|
<label for="password-input">Password</label>
|
||||||
|
<input name="password" type="password" placeholder="twixrox" />
|
||||||
|
</div>
|
||||||
|
<Show when={loggingIn.error?.fieldErrors?.password}>
|
||||||
|
<p role="alert">{loggingIn.error.fieldErrors.password}</p>
|
||||||
|
</Show>
|
||||||
|
<Show when={loggingIn.error}>
|
||||||
|
<p role="alert" id="error-message">
|
||||||
|
{loggingIn.error.message}
|
||||||
|
</p>
|
||||||
|
</Show>
|
||||||
|
<button type="submit">{data() ? "Login" : ""}</button>
|
||||||
|
</Form>
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
|
@ -1,21 +1,54 @@
|
||||||
import { For, batch, createEffect, createSignal } from "solid-js";
|
import { For, batch, createEffect, createSignal } from "solid-js";
|
||||||
import { SetStoreFunction, Store, createStore } from "solid-js/store";
|
import { SetStoreFunction, Store, createStore } from "solid-js/store";
|
||||||
|
import { createServerAction$ } from "solid-start/server";
|
||||||
|
|
||||||
type TodoItem = { title: string; done: boolean };
|
import { db, todosApp } from "~/db";
|
||||||
|
|
||||||
const Todos = () => {
|
interface TodoItem {
|
||||||
|
title: string;
|
||||||
|
done: boolean;
|
||||||
|
committed: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Todos() {
|
||||||
const [newTitle, setTitle] = createSignal("");
|
const [newTitle, setTitle] = createSignal("");
|
||||||
const [todos, setTodos] = createLocalStore<TodoItem[]>("todos", []);
|
const [todos, setTodos] = createTodoStore<TodoItem[]>("todos", []);
|
||||||
|
|
||||||
|
const [adding, add] = createServerAction$(
|
||||||
|
async ({ title }: { title: string }) => {
|
||||||
|
const metadata_keys = new Map();
|
||||||
|
const keyOf = (appKey: string) => ({ appId: todosApp.id, appKey });
|
||||||
|
metadata_keys.set(keyOf("title"), title);
|
||||||
|
|
||||||
|
const node = await db.createNode({
|
||||||
|
label: `todo-${title}`,
|
||||||
|
metadata_keys,
|
||||||
|
});
|
||||||
|
console.log("Created node", node);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
const addTodo = (e: SubmitEvent) => {
|
const addTodo = (e: SubmitEvent) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
const idx = todos.length;
|
||||||
|
const title = newTitle();
|
||||||
|
|
||||||
batch(() => {
|
batch(() => {
|
||||||
setTodos(todos.length, {
|
setTodos(idx, {
|
||||||
title: newTitle(),
|
title,
|
||||||
done: false,
|
done: false,
|
||||||
|
committed: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
setTitle("");
|
setTitle("");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
add({ title });
|
||||||
|
console.log("Adding", adding);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -30,6 +63,7 @@ const Todos = () => {
|
||||||
/>
|
/>
|
||||||
<button>+</button>
|
<button>+</button>
|
||||||
</form>
|
</form>
|
||||||
|
Todos:
|
||||||
<For each={todos}>
|
<For each={todos}>
|
||||||
{(todo, i) => (
|
{(todo, i) => (
|
||||||
<div>
|
<div>
|
||||||
|
@ -51,22 +85,27 @@ const Todos = () => {
|
||||||
</For>
|
</For>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
}
|
||||||
|
|
||||||
export default Todos;
|
function createTodoStore<T extends object>(
|
||||||
|
|
||||||
export function createLocalStore<T extends object>(
|
|
||||||
name: string,
|
name: string,
|
||||||
init: T
|
init: T
|
||||||
): [Store<T>, SetStoreFunction<T>] {
|
): [Store<T>, SetStoreFunction<T>] {
|
||||||
const localState = localStorage.getItem(name);
|
// const localState = localStorage.getItem(name);
|
||||||
|
|
||||||
const [state, setState] = createStore<T>(
|
const [state, setState] = createStore<T>(
|
||||||
localState ? JSON.parse(localState) : init
|
init
|
||||||
|
// localState ? JSON.parse(localState) : init
|
||||||
);
|
);
|
||||||
createEffect(() => localStorage.setItem(name, JSON.stringify(state)));
|
|
||||||
|
createEffect(() => {
|
||||||
|
console.log("Calling local storage");
|
||||||
|
// localStorage.setItem(name, JSON.stringify(state));
|
||||||
|
});
|
||||||
|
|
||||||
return [state, setState];
|
return [state, setState];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function removeIndex<T>(array: readonly T[], index: number): T[] {
|
function removeIndex<T>(array: readonly T[], index: number): T[] {
|
||||||
return [...array.slice(0, index), ...array.slice(index + 1)];
|
return [...array.slice(0, index), ...array.slice(index + 1)];
|
||||||
}
|
}
|
|
@ -1,28 +0,0 @@
|
||||||
import express from "express";
|
|
||||||
|
|
||||||
import Database from "../core/db";
|
|
||||||
|
|
||||||
const app = express();
|
|
||||||
|
|
||||||
app.get("/", (req, res) => {
|
|
||||||
res.send("Welcome to the Dinosaur API!");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a node
|
|
||||||
app.post("/api/node", async (req, res) => {
|
|
||||||
const node = await Database.createNode({
|
|
||||||
label: "hellosu",
|
|
||||||
other_nodes: new Map(),
|
|
||||||
edges: new Set(),
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log("node", node);
|
|
||||||
|
|
||||||
res.json({ success: true });
|
|
||||||
});
|
|
||||||
|
|
||||||
import todos from "./todos";
|
|
||||||
app.use("/api/todos", todos);
|
|
||||||
|
|
||||||
console.log("Listening.");
|
|
||||||
app.listen(8605, "0.0.0.0");
|
|
|
@ -1,8 +0,0 @@
|
||||||
import {Router} from "express";
|
|
||||||
|
|
||||||
const router = Router();
|
|
||||||
|
|
||||||
router.get("/", async (req, res) => {
|
|
||||||
});
|
|
||||||
|
|
||||||
export default router;
|
|
|
@ -1,20 +1,17 @@
|
||||||
{
|
{
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"strict": true,
|
"allowSyntheticDefaultImports": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
"target": "ESNext",
|
"target": "ESNext",
|
||||||
"module": "ESNext",
|
"module": "ESNext",
|
||||||
"moduleResolution": "node",
|
"moduleResolution": "node",
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"jsx": "preserve",
|
|
||||||
"jsxImportSource": "solid-js",
|
"jsxImportSource": "solid-js",
|
||||||
"types": ["vite/client"],
|
"jsx": "preserve",
|
||||||
"noEmit": true,
|
"strict": true,
|
||||||
"isolatedModules": true,
|
"types": ["solid-start/env"],
|
||||||
|
"baseUrl": "./",
|
||||||
"baseUrl": ".",
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@panorama": ["src/*"]
|
"~/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
import { defineConfig } from "vite";
|
|
||||||
import solidPlugin from "vite-plugin-solid";
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
plugins: [solidPlugin()],
|
|
||||||
server: {
|
|
||||||
port: 3000,
|
|
||||||
},
|
|
||||||
build: {
|
|
||||||
target: "esnext",
|
|
||||||
},
|
|
||||||
});
|
|
7
vite.config.ts
Normal file
7
vite.config.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import solid from "solid-start/vite";
|
||||||
|
import { defineConfig } from "vite";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [solid()],
|
||||||
|
ssr: { external: ["@prisma/client"] },
|
||||||
|
});
|
Loading…
Reference in a new issue