Back to packages list

Vals using drizzle-orm

Description from the NPM package:
Drizzle ORM package for SQL databases
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import { sql } from "npm:drizzle-orm@0.30.7";
import { sqliteTable, text } from "npm:drizzle-orm@0.30.7/sqlite-core";
import { z } from "npm:zod@3.22.4";
export type UserId = string & { readonly UserId: unique symbol };
export const UserId = z
.string()
.startsWith("u_")
.transform((k) => k as UserId);
export const users_table = sqliteTable("users", {
user_id: text("user_id").$type<UserId>().primaryKey(),
username: text("username").unique().notNull(),
first_name: text("first_name"),
last_name: text("last_name"),
email_address: text("email_address").notNull(),
clerk_user_id: text("clerk_user_id").unique().notNull(),
});
export type InsertUser = typeof users_table.$inferInsert;
export type SelectUser = typeof users_table.$inferSelect;
export const schema = { users_table };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { generateRandomString } from "https://esm.town/v/greg0r/generateRandomString?v=1";
import { sqlite } from "https://esm.town/v/std/sqlite?v=4";
import { home, scopesRoute } from "https://esm.town/v/stevekrouse/spotify_helpers";
import { spotifyRefreshToken } from "https://esm.town/v/stevekrouse/spotifyRefreshToken";
import { spotifyRequestToken } from "https://esm.town/v/stevekrouse/spotifyRequestToken";
import { thisWebURL } from "https://esm.town/v/stevekrouse/thisWebURL";
import { eq, sql } from "npm:drizzle-orm";
import { drizzle } from "npm:drizzle-orm/libsql";
import { integer, sqliteTable, text } from "npm:drizzle-orm/sqlite-core";
import { getCookie, setCookie } from "npm:hono/cookie";
import { Hono } from "npm:hono@3";
// await sqlite.execute("CREATE TABLE spot (id text primary key, data text)")
export const db = drizzle(sqlite as any);
export const table = sqliteTable("SPOTIFY_AUTH", {
id: text("id").primaryKey(),
data: text("data"),
});
const thisURL = thisWebURL();
const redirect_uri = thisURL + "/callback";
const app = new Hono();
app.use("*", async (c, next) => {
const state = getCookie(c, "state") ?? generateRandomString(16);
c.set("state", state);
await next();
setCookie(c, "state", state);
});
app.get("/", home);
app.get("/scopes", scopesRoute);
app.get("/login", async (c) => {
const state = c.get("state");
const scopes = c.req.queries("scopes[]").join(" ");
await db.insert(table).values([{ id: state }]);
return c.redirect(
`https://accounts.spotify.com/authorize?response_type=code&client_id=${
encodeURIComponent(Deno.env.get("SPOTIFY_CLIENT_ID"))
}&scope=${encodeURIComponent(scopes)}&redirect_uri=${encodeURIComponent(redirect_uri)}&state=${state}`,
);
});
app.get("/callback", async (c) => {
const code = c.req.query("code");
const state = c.req.query("state") as string;
if (state !== c.get("state")) {
return c.html("State mismatch 1");
}
const rowInitialResult = await db.select().from(table).where(eq(table.id, state)).limit(1);
const rowInitial = rowInitialResult[0];
if (!rowInitial) {
return c.html("State mismatch 2");
}
if (rowInitial.data) {
return c.html("Already authenticated for that state");
}
const data = await spotifyRequestToken({
code,
client_id: Deno.env.get("SPOTIFY_CLIENT_ID"),
client_secret: Deno.env.get("SPOTIFY_CLIENT_SECRET"),
redirect_uri,
});
data.now = Date.now(); // to help us calculate when to refresh
if (data.error) return c.json(data.error);
if (!data.access_token) return c.json("No access token");
await db.update(table).set({ data: JSON.stringify(data) }).where(eq(table.id, state));
return c.redirect("/token?state=" + state);
});
app.get("/token", async (c) => {
const state = c.req.query("state") as string;
const authData = await db.select().from(table).where(eq(table.id, state)).limit(1);
if (!authData.length) return c.json("No auth data found for supplied state");
const data = JSON.parse(authData[0].data);
let expiresAt = data.now + (data.expires_in * 1000);
if (expiresAt < Date.now()) {
let refresh = await spotifyRefreshToken({
refresh_token: data.refresh_token,
client_id: Deno.env.get("SPOTIFY_CLIENT_ID"),
client_secret: Deno.env.get("SPOTIFY_CLIENT_SECRET"),
});
if (refresh.error) return c.json("Refresh error: " + refresh.error);
if (!refresh.access_token) return c.json("No refresh access token");
refresh.now = Date.now();
await db.update(table).set({ data: JSON.stringify(refresh) }).where(eq(table.id, state));
}
return c.json(data.access_token);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import { slackPost } from "https://esm.town/v/glommer/sendMsgToSlack";
import { sqlite } from "https://esm.town/v/std/sqlite";
import { sql } from "npm:drizzle-orm";
import { drizzle } from "npm:drizzle-orm/libsql";
import { integer, sqliteTable, text } from "npm:drizzle-orm/sqlite-core";
const db = drizzle(sqlite as any);
const threadsTbl = sqliteTable("threads", {
id: text("id").primaryKey(),
last_message_id: text("last_message_id"),
});
async function getKnownThreads() {
const result = await db.select().from(threadsTbl);
return result.reduce((r, { id, last_message_id }) => {
r[id] = parseInt(last_message_id ?? "0");
return r;
}, {});
}
async function getNewThreads() {
const resp = await fetch(`https://discord.com/api/guilds/${guild}/threads/active`, {
headers: {
"Authorization": `Bot ${token}`,
},
});
if (!resp.ok) {
const err = await resp.json();
console.log(`response failed: ${err}`);
return;
}
const j = await resp.json();
return j.threads;
}
export async function getThreadsActivity(
token: string,
guild: string,
slackToken: string,
slackChannel: string,
) {
const knownThreads = await getKnownThreads();
const threads = await getNewThreads();
const ops = [db.delete(threadsTbl)];
for (let i = 0; i < threads.length; i++) {
const t = threads[i];
const id = t.id;
const name = t.name;
// don't do parseInt here, need to be text, so we can save text back to sqlite
const last_message_id = t.last_message_id;
const parent_id = t.parent_id;
const lastKnown = knownThreads[id] ?? 0;
if (parseInt(last_message_id) > lastKnown) {
await slackPost(
slackToken,
slackChannel,
`New activity for "${name}: https://discord.com/channels/${guild}/${id}/${id}"`,
);
}
ops.push(db.insert(threadsTbl).values({ id, last_message_id }));
}
await db.batch(ops);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
import { slackPost } from "https://esm.town/v/glommer/sendMsgToSlack";
import { sqlite } from "https://esm.town/v/std/sqlite";
import { sql } from "npm:drizzle-orm";
import { drizzle } from "npm:drizzle-orm/libsql";
import { integer, sqliteTable, text } from "npm:drizzle-orm/sqlite-core";
const db = drizzle(sqlite as any);
const threadsTbl = sqliteTable("threads", {
id: text("id").primaryKey(),
last_message_id: text("last_message_id"),
});
async function getKnownThreads() {
const result = await db.select().from(threadsTbl);
return result.reduce((r, { id, last_message_id }) => {
r[id] = parseInt(last_message_id ?? "0");
return r;
}, {});
}
async function getNewThreads() {
const resp = await fetch(`https://discord.com/api/guilds/${guild}/threads/active`, {
headers: {
"Authorization": `Bot ${token}`,
},
});
if (!resp.ok) {
const err = await resp.json();
console.log(`response failed: ${err}`);
return;
}
const j = await resp.json();
return j.threads;
}
export async function getThreadsActivity(
token: string,
guild: string,
slackToken: string,
slackChannel: string,
) {
const knownThreads = await getKnownThreads();
const threads = await getNewThreads();
const ops = [db.delete(threadsTbl)];
for (let i = 0; i < threads.length; i++) {
const t = threads[i];
const id = t.id;
const name = t.name;
// don't do parseInt here, need to be text, so we can save text back to sqlite
const last_message_id = t.last_message_id;
const parent_id = t.parent_id;
const lastKnown = knownThreads[id] ?? 0;
if (parseInt(last_message_id) > lastKnown) {
await slackPost(
slackToken,
slackChannel,
`New activity for "${name}: https://discord.com/channels/${guild}/${id}/${id}"`,
);
}
ops.push(db.insert(threadsTbl).values({ id, last_message_id }));
}
await db.batch(ops);
}
1
2
3
4
5
6
7
8
9
10
11
import { turso } from "https://esm.town/v/stevekrouse/turso";
import { sql } from "npm:drizzle-orm@0.28.6";
import { drizzle } from "npm:drizzle-orm@0.28.6/libsql";
import { integer, sqliteTable, text } from "npm:drizzle-orm@0.28.6/sqlite-core";
const db = drizzle(turso());
const kv = sqliteTable("kv", {
key: text("key").primaryKey(),
value: text("value").notNull(),
});
export let tursoDrizzleExample2 = db.select().from(kv).all();
1
2
3
4
5
6
7
8
9
10
11
import { sqlite } from "https://esm.town/v/std/sqlite";
import { sql } from "npm:drizzle-orm";
import { drizzle } from "npm:drizzle-orm/libsql";
import { integer, sqliteTable, text } from "npm:drizzle-orm/sqlite-core";
const db = drizzle(sqlite as any);
const kv = sqliteTable("kv", {
key: text("key").primaryKey(),
value: text("value").notNull(),
});
export let sqliteDrizzleExample = db.select().from(kv).all();
1
Next