15const name = getValNameFromUrl(import.meta.url);
16
17async function createPage(content: unknown) {
18 const [
19 footer,
7const USERNAME = extractValInfo(import.meta.url).author;
8
9export async function MyFooter(logo = valTownLogoAuto) {
10 const recommendation = rootValRef().handle === USERNAME
11 ? html`<span class="recommends">${await recommends()}</span>`
35}
36
37export default async function(req) {
38 const { Layout } = await import("https://esm.town/v/postpostscript/Layout");
39 return htmlResponse`${Layout`
5const ENDPOINT = getValEndpointFromUrl(import.meta.url);
6
7export function profileImageUrl(username: string) {
8 return `${ENDPOINT}/${username}`;
9}
10
11export function ProfileImage(
12 username: string,
13 className = "profile-image",
16}
17
18export function Profile(username: string) {
19 return html`
20 <span
34}
35
36export default async function(req: Request) {
37 const { pathname } = new URL(req.url);
38 if (pathname.length <= 1) {
3
4type Index = { x: number; y: number };
5function next_i(i: Index): Index | null {
6 if (i.x === COLS - 1 && i.y === ROWS - 1) {
7 return null;
13}
14
15function valid_row(sudoku: Sudoku, i: Index): boolean {
16 const seen = new Set();
17 for (let col = 0; col < COLS; col++) {
27}
28
29function valid_col(sudoku: Sudoku, i: Index): boolean {
30 const seen = new Set();
31 for (let row = 0; row < ROWS; row++) {
41}
42
43function valid_square(sudoku: Sudoku, i: Index): boolean {
44 const col_offset = Math.floor(i.x / 3) * 3;
45 const row_offset = Math.floor(i.y / 3) * 3;
60}
61
62export function solve(sudoku: Sudoku): Sudoku | null {
63 sudoku = Sudoku.parse(sudoku);
64
12};
13
14export function pathAsScope({ val = rootValRef(), basePath = "/", log = false }: PathAsScopeOptions = {}) {
15 const { handle, name } = val;
16 const valName = `@${handle}/${name}`;
56}
57
58export function pathMatches(path: string, matchString: string) {
59 const pathParts = ("/" + path.replace(/^\/|\/$/g, "")).split("/");
60 const matchParts = ("/" + matchString.replace(/^\/|\/$/g, "")).split("/");
5};
6
7export function basicAuth(next: (Request) => Response | Promise<Response>, options: BasicAuthOptions) {
8 return async (req: Request) => {
9 if (req.headers.get("referer") == "https://www.val.town/") {
33}
34
35function extractCredentials(authorization): { username: string; password: string } {
36 const parts = authorization.split(" ");
37 if (parts[0] != "Basic") {
47}
48
49async function isRequestAuthenticated(req, userTable: string) {
50 if (!req.headers.has("authorization")) {
51 return false;
4import {Scrypt, generateId} from "npm:lucia"
5
6export async function createTables(userTable: string, sessionTable: string) {
7 return sqlite.batch([
8 `CREATE TABLE ${userTable} (
20}
21
22export async function createUser(table: string, username: string, password: string) {
23 if (
24 username.length < 3
43}
44
45export async function getUser(
46 table: string,
47 username: string,
56}
57
58export async function verifyPassword(hashed_password: string, password: string): Promise<boolean> {
59 return new Scrypt().verify(hashed_password, password);
60}
127}
128
129function transformIntoDatabaseSession(raw: SessionSchema): DatabaseSession {
130 const { id, user_id: userId, expires_at: expiresAtUnix, ...attributes } = raw;
131 return {
137}
138
139function transformIntoDatabaseUser(raw: UserSchema): DatabaseUser {
140 const { id, ...attributes } = raw;
141 return {
145}
146
147function escapeName(val: string): string {
148 return "`" + val + "`";
149}
1import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
2
3export async function listSqliteTables() {
4 return (await sqlite.execute(
5 `select name from sqlite_schema where type='table' and name != 'libsql_wasm_func_table' and name != 'sqlite_sequence'`,
57};
58
59function TestItem({ test, run }: { test: Test; run: () => void }) {
60 return (
61 <div>
75}
76
77function groupBySlug(tests: Test[]): Record<string, Test[]> {
78 const groups = {};
79 for (const test of Object.values(tests)) {
89}
90
91function useTests(initialTests: Test[]) {
92 const id = (test: Test) => `${test.val.name}/${test.name}`;
93 const [tests, setTests] = useState(Object.fromEntries(initialTests.map((test) => {
118}
119
120function TestExplorerView({ tests }: Props) {
121 const { groups, runTest } = useTests(tests);
122 return (
187}
188
189export default function(props: { tests: Test[] }) {
190 return (
191 <>