Compare commits
5 commits
1a8ebaf88d
...
0344976747
Author | SHA1 | Date | |
---|---|---|---|
|
0344976747 | ||
|
2d53428f56 | ||
|
20e50346f4 | ||
|
5e996b27d3 | ||
|
0480be5ded |
|
@ -94,7 +94,7 @@
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
devShells.default = pkgs.mkShell {
|
devShells.default = pkgs.mkShell {
|
||||||
buildInputs = with pkgs; [ go pigeon nodejs sqlite git-bug openssl ];
|
buildInputs = with pkgs; [ go pigeon nodejs sqlite git-bug openssl flyctl skopeo ];
|
||||||
|
|
||||||
# TODO:
|
# TODO:
|
||||||
# Shell Aliases don't work for direnv because they're not shell portable
|
# Shell Aliases don't work for direnv because they're not shell portable
|
||||||
|
|
23
fly.toml
Normal file
23
fly.toml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# fly.toml app configuration file generated for mast-react-vite-cold-snowflake-8783 on 2025-02-19T23:28:02-08:00
|
||||||
|
#
|
||||||
|
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
|
||||||
|
#
|
||||||
|
|
||||||
|
app = 'mast-react-vite'
|
||||||
|
primary_region = 'sea'
|
||||||
|
|
||||||
|
[build]
|
||||||
|
image = 'react-server:latest'
|
||||||
|
|
||||||
|
[http_service]
|
||||||
|
internal_port = 8080
|
||||||
|
force_https = true
|
||||||
|
auto_stop_machines = true
|
||||||
|
auto_start_machines = true
|
||||||
|
min_machines_running = 0
|
||||||
|
processes = ['app']
|
||||||
|
|
||||||
|
[[vm]]
|
||||||
|
memory = '1gb'
|
||||||
|
cpu_kind = 'shared'
|
||||||
|
cpus = 1
|
|
@ -54,56 +54,60 @@ export function DataTable<TData, TValue>({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div >
|
<div className="w-full overflow-x-auto">
|
||||||
<Table >
|
<Table className="min-w-full table-fixed md:table-auto">
|
||||||
<TableHeader className="bg-accent">
|
<TableHeader className="bg-accent flex flex-row md:table-header-group">
|
||||||
{table.getHeaderGroups().map((headerGroup) => (
|
{table.getHeaderGroups().map((headerGroup) => (
|
||||||
<TableRow key={headerGroup.id}>
|
<TableRow key={headerGroup.id} className="flex flex-row flex-wrap md:table-row">
|
||||||
{headerGroup.headers.map((header) => {
|
{headerGroup.headers.map((header) => (
|
||||||
return (
|
<TableHead
|
||||||
<TableHead key={header.id}
|
key={header.id}
|
||||||
className="relative text-foreground"
|
className="relative text-foreground flex-1 min-w-[20px] flex items-center px-4 py-2 md:table-cell"
|
||||||
style={{
|
style={{
|
||||||
width: header.getSize(),
|
width: header.getSize(),
|
||||||
}}
|
}}
|
||||||
>
|
|
||||||
{header.isPlaceholder
|
|
||||||
? null
|
|
||||||
: flexRender(
|
|
||||||
header.column.columnDef.header,
|
|
||||||
header.getContext()
|
|
||||||
)}
|
|
||||||
</TableHead>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
</TableRow>
|
|
||||||
))}
|
|
||||||
</TableHeader>
|
|
||||||
<TableBody>
|
|
||||||
{table.getRowModel().rows?.length ? (
|
|
||||||
table.getRowModel().rows.map((row) => (
|
|
||||||
<TableRow
|
|
||||||
key={row.id}
|
|
||||||
data-state={row.getIsSelected() && "selected"}
|
|
||||||
>
|
>
|
||||||
{row.getVisibleCells().map((cell) => (
|
{header.isPlaceholder
|
||||||
<TableCell key={cell.id}>
|
? null
|
||||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
: flexRender(
|
||||||
</TableCell>
|
header.column.columnDef.header,
|
||||||
))}
|
header.getContext()
|
||||||
</TableRow>
|
)}
|
||||||
))
|
</TableHead>
|
||||||
) : (
|
))}
|
||||||
<TableRow>
|
</TableRow>
|
||||||
<TableCell colSpan={columns.length} className="h-24 text-center">
|
))}
|
||||||
No results.
|
</TableHeader>
|
||||||
</TableCell>
|
<TableBody className="flex flex-col md:table-row-group">
|
||||||
|
{table.getRowModel().rows?.length ? (
|
||||||
|
table.getRowModel().rows.map((row) => (
|
||||||
|
<TableRow
|
||||||
|
key={row.id}
|
||||||
|
data-state={row.getIsSelected() && "selected"}
|
||||||
|
className="flex flex-row flex-wrap md:table-row"
|
||||||
|
>
|
||||||
|
{row.getVisibleCells().map((cell) => (
|
||||||
|
<TableCell
|
||||||
|
key={cell.id}
|
||||||
|
className="flex-1 min-w-[20px] flex items-center px-4 py-2 md:table-cell"
|
||||||
|
>
|
||||||
|
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||||
|
</TableCell>
|
||||||
|
))}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)}
|
))
|
||||||
</TableBody>
|
) : (
|
||||||
</Table>
|
<TableRow>
|
||||||
</div>
|
<TableCell colSpan={columns.length} className="h-24 text-center">
|
||||||
)
|
No results.
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
)}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,14 +2,15 @@ import { createRoot } from 'react-dom/client'
|
||||||
import './index.css'
|
import './index.css'
|
||||||
import App from "./App.tsx";
|
import App from "./App.tsx";
|
||||||
|
|
||||||
|
import { DBAsync } from "@vlcn.io/xplat-api";
|
||||||
import initWasm from '@vlcn.io/crsqlite-wasm';
|
import initWasm from '@vlcn.io/crsqlite-wasm';
|
||||||
import wasmUrl from '@vlcn.io/crsqlite-wasm/crsqlite.wasm?url';
|
import wasmUrl from '@vlcn.io/crsqlite-wasm/crsqlite.wasm?url';
|
||||||
import tblrx from '@vlcn.io/rx-tbl';
|
import tblrx from '@vlcn.io/rx-tbl';
|
||||||
|
|
||||||
const sqlite = await initWasm(() => wasmUrl);
|
const initDb = async () => {
|
||||||
|
const sqlite = await initWasm(() => wasmUrl);
|
||||||
const db = await sqlite.open("todo.db");
|
const db: DBAsync = await sqlite.open("todo.db");
|
||||||
await db.exec(`
|
await db.exec(`
|
||||||
CREATE TABLE IF NOT EXISTS todos (
|
CREATE TABLE IF NOT EXISTS todos (
|
||||||
id BLOB PRIMARY KEY NOT NULL,
|
id BLOB PRIMARY KEY NOT NULL,
|
||||||
description TEXT,
|
description TEXT,
|
||||||
|
@ -22,16 +23,19 @@ await db.exec(`
|
||||||
completed INTEGER NOT NULL DEFAULT 0
|
completed INTEGER NOT NULL DEFAULT 0
|
||||||
);
|
);
|
||||||
SELECT crsql_as_crr('todos');
|
SELECT crsql_as_crr('todos');
|
||||||
`);
|
`);
|
||||||
|
const rx = tblrx(db);
|
||||||
|
return {db, rx};
|
||||||
|
}
|
||||||
|
|
||||||
const rx = tblrx(db);
|
const init = async () => {
|
||||||
const ctx = { db, rx };
|
const ctx = await initDb();
|
||||||
|
createRoot(document.getElementById("root") as HTMLElement).render(
|
||||||
|
<main className="min-h-screen flex flex-col py-12 bg-background text-gray-200">
|
||||||
|
<App ctx={ctx} />
|
||||||
|
</main>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
document.getElementById("root")!.classList.add("dark");
|
document.getElementById("root")!.classList.add("dark");
|
||||||
|
init();
|
||||||
createRoot(document.getElementById("root") as HTMLElement).render(
|
|
||||||
<main className="min-h-screen flex flex-col py-12 bg-background text-gray-200">
|
|
||||||
<App ctx={ctx} />
|
|
||||||
</main>
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,9 @@ import path from "path"
|
||||||
|
|
||||||
// https://vite.dev/config/
|
// https://vite.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
|
server: {
|
||||||
|
host: true // This enables listening on all network interfaces
|
||||||
|
},
|
||||||
plugins: [react()],
|
plugins: [react()],
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
alias: {
|
||||||
|
|
18
parser/command_parser.d.ts
vendored
Normal file
18
parser/command_parser.d.ts
vendored
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
export interface Part {
|
||||||
|
type: 'text';
|
||||||
|
value: string;
|
||||||
|
reconstruct: () => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface Command {
|
||||||
|
type: 'add' | 'filter' | 'done';
|
||||||
|
description: string;
|
||||||
|
attributes: string[];
|
||||||
|
filters: string[];
|
||||||
|
project: string;
|
||||||
|
tags: string;
|
||||||
|
parts: Part[];
|
||||||
|
reconstruct: () => string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function parse(input: string): Command;
|
54
parser/filter_go.peg
Normal file
54
parser/filter_go.peg
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
package parser
|
||||||
|
|
||||||
|
type IdFilter struct {
|
||||||
|
Ids []int
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter <- first:(IdRange / SingleId) rest:(',' (IdRange / SingleId))* {
|
||||||
|
var ids []int
|
||||||
|
first := toIntSlice(first)
|
||||||
|
ids = append(ids, first...)
|
||||||
|
|
||||||
|
if rest != nil {
|
||||||
|
for _, r := range rest.([]interface{}) {
|
||||||
|
restIds := toIntSlice(r.([]interface{})[1])
|
||||||
|
ids = append(ids, restIds...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &IdFilter{Ids: ids}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
IdRange <- start:Integer '-' end:Integer {
|
||||||
|
start := start.(int)
|
||||||
|
end := end.(int)
|
||||||
|
var ids []int
|
||||||
|
for i := start; i <= end; i++ {
|
||||||
|
ids = append(ids, i)
|
||||||
|
}
|
||||||
|
return ids, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleId <- id:Integer {
|
||||||
|
return []int{id.(int)}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer <- [0-9]+ {
|
||||||
|
val := string(c.text)
|
||||||
|
n, _ := strconv.Atoi(val)
|
||||||
|
return n, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_ <- [ \t]*
|
||||||
|
|
||||||
|
{
|
||||||
|
func toIntSlice(v interface{}) []int {
|
||||||
|
if slice, ok := v.([]int); ok {
|
||||||
|
return slice
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
31
parser/filter_js.peg
Normal file
31
parser/filter_js.peg
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
function makeIdFilter(ids) {
|
||||||
|
return {
|
||||||
|
type: 'id_filter',
|
||||||
|
ids: ids.flat(),
|
||||||
|
reconstruct: function() {
|
||||||
|
return this.ids.join(',');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Filter = first:(IdRange / SingleId) rest:("," (IdRange / SingleId))* {
|
||||||
|
return makeIdFilter([first, ...rest.map(r => r[1])]);
|
||||||
|
}
|
||||||
|
|
||||||
|
IdRange = start:Integer "-" end:Integer {
|
||||||
|
const ids = [];
|
||||||
|
for (let i = start; i <= end; i++) {
|
||||||
|
ids.push(i);
|
||||||
|
}
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
SingleId = id:Integer {
|
||||||
|
return [id];
|
||||||
|
}
|
||||||
|
|
||||||
|
Integer = digits:[0-9]+ {
|
||||||
|
return parseInt(digits.join(''), 10);
|
||||||
|
}
|
7
scripts/deploy.sh
Normal file
7
scripts/deploy.sh
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
PROJECT_NAME=mast-react-vite
|
||||||
|
nix build .#react-server
|
||||||
|
skopeo --insecure-policy --debug copy docker-archive:"./result" "docker://registry.fly.io/$PROJECT_NAME:latest" --dest-creds x:"$(flyctl auth token)" --format v2s2
|
||||||
|
flyctl deploy -i "registry.fly.io/$PROJECT_NAME:latest" --remote-only
|
||||||
|
|
Loading…
Reference in a new issue