Move to sqlite off cloud

This commit is contained in:
2026-03-06 18:49:41 +02:00
parent 27b7d87e68
commit 1b31f3194d
23 changed files with 266 additions and 655 deletions

View File

@@ -5,13 +5,13 @@ import {
availableTones,
availableUnits,
} from "~/shared/constants";
//
const bodySchema = z.strictObject({
enabled: z.boolean(),
language: z.enum(availableLanguages),
units: z.enum(availableUnits),
tone: z.array(z.enum(availableTones)),
highlights: z.array(z.enum(availableHighlights)),
units: z.enum(availableUnits).default(availableUnits[1]),
tone: z.array(z.enum(availableTones)).default([]),
highlights: z.array(z.enum(availableHighlights)).default([]),
});
export default defineEventHandler(async (event) => {

View File

@@ -32,25 +32,25 @@ export default defineEventHandler(async (event) => {
user: user!,
}).catch((err) => [err]);
if (aiError) {
console.log(aiError.message);
throw createError({
statusCode: 500,
message: `OPENAI API: ${aiError.message}`,
});
}
console.log(JSON.stringify(stravaRequestBody));
// await strava!(`activities/${body.object_id}`, {
// method: "PUT",
// body: {
// name: stravaRequestBody.name,
// description: stravaRequestBody.description,
// },
// }).catch((error) => {
// throw createError({
// statusCode: 500,
// message: `Strava API: ${error.message}`,
// });
// });
await strava!(`activities/${body.object_id}`, {
method: "PUT",
body: {
name: (stravaRequestBody.name as String).replaceAll("—", ","),
description: (stravaRequestBody.description as String).replaceAll(
"—",
",",
),
},
}).catch((error) => {
throw createError({
statusCode: 500,
message: `Strava API: ${error.message}`,
});
});
});

View File

@@ -4,8 +4,6 @@ import { eq } from "drizzle-orm";
export default defineEventHandler(async (event) => {
await validateHookdeck(event);
const posthog = event.context.posthog;
const body = await readBody(event);
const db = useDrizzle();
@@ -13,13 +11,6 @@ export default defineEventHandler(async (event) => {
return;
}
const user = await db.query.users.findFirst({
where: (f, o) => o.eq(f.id, get(body, "object_id")),
with: {
preferences: true,
},
});
await db
.delete(tables.users)
.where(eq(tables.users.id, get(body, "object_id")));

View File

@@ -0,0 +1,28 @@
CREATE TABLE `preferences` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`user_id` numeric,
`data` text,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `preferences_user_id_unique` ON `preferences` (`user_id`);--> statement-breakpoint
CREATE TABLE `tokens` (
`id` integer PRIMARY KEY AUTOINCREMENT NOT NULL,
`user_id` numeric,
`refresh_token` text,
`access_token` text,
`expires_at` integer NOT NULL,
FOREIGN KEY (`user_id`) REFERENCES `users`(`id`) ON UPDATE no action ON DELETE cascade
);
--> statement-breakpoint
CREATE UNIQUE INDEX `tokens_user_id_unique` ON `tokens` (`user_id`);--> statement-breakpoint
CREATE TABLE `users` (
`id` numeric PRIMARY KEY NOT NULL,
`name` text NOT NULL,
`avatar` text,
`city` text,
`country` text,
`sex` text,
`weight` integer,
`created_at` integer NOT NULL
);

View File

@@ -1,29 +0,0 @@
CREATE TABLE "preferences" (
"id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "preferences_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
"user_id" integer,
"data" jsonb,
CONSTRAINT "preferences_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
CREATE TABLE "tokens" (
"id" integer PRIMARY KEY GENERATED ALWAYS AS IDENTITY (sequence name "tokens_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
"user_id" integer,
"refresh_token" text,
"access_token" text,
"expires_at" timestamp DEFAULT now() NOT NULL,
CONSTRAINT "tokens_user_id_unique" UNIQUE("user_id")
);
--> statement-breakpoint
CREATE TABLE "users" (
"id" integer PRIMARY KEY NOT NULL,
"name" text NOT NULL,
"avatar" text NOT NULL,
"city" text,
"country" text,
"sex" text,
"weight" numeric,
"created_at" timestamp DEFAULT now() NOT NULL
);
--> statement-breakpoint
ALTER TABLE "preferences" ADD CONSTRAINT "preferences_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
ALTER TABLE "tokens" ADD CONSTRAINT "tokens_user_id_users_id_fk" FOREIGN KEY ("user_id") REFERENCES "public"."users"("id") ON DELETE cascade ON UPDATE no action;

View File

@@ -1 +0,0 @@
ALTER TABLE "users" ADD COLUMN "premium" boolean;

View File

@@ -1 +0,0 @@
ALTER TABLE "users" ALTER COLUMN "premium" SET NOT NULL;

View File

@@ -1,210 +1,204 @@
{
"id": "c8519a52-b999-48f3-b532-42a5678e3905",
"version": "6",
"dialect": "sqlite",
"id": "d9537942-cba2-4af4-8396-533366512937",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.preferences": {
"preferences": {
"name": "preferences",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "preferences_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
"autoincrement": true
},
"user_id": {
"name": "user_id",
"type": "integer",
"type": "numeric",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"data": {
"name": "data",
"type": "jsonb",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
}
},
"indexes": {
"preferences_user_id_unique": {
"name": "preferences_user_id_unique",
"columns": [
"user_id"
],
"isUnique": true
}
},
"indexes": {},
"foreignKeys": {
"preferences_user_id_users_id_fk": {
"name": "preferences_user_id_users_id_fk",
"tableFrom": "preferences",
"tableTo": "users",
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"preferences_user_id_unique": {
"name": "preferences_user_id_unique",
"nullsNotDistinct": false,
"columns": ["user_id"]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
"uniqueConstraints": {},
"checkConstraints": {}
},
"public.tokens": {
"tokens": {
"name": "tokens",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "tokens_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
"autoincrement": true
},
"user_id": {
"name": "user_id",
"type": "integer",
"type": "numeric",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": "now()"
"autoincrement": false
}
},
"indexes": {
"tokens_user_id_unique": {
"name": "tokens_user_id_unique",
"columns": [
"user_id"
],
"isUnique": true
}
},
"indexes": {},
"foreignKeys": {
"tokens_user_id_users_id_fk": {
"name": "tokens_user_id_users_id_fk",
"tableFrom": "tokens",
"tableTo": "users",
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"tokens_user_id_unique": {
"name": "tokens_user_id_unique",
"nullsNotDistinct": false,
"columns": ["user_id"]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
"uniqueConstraints": {},
"checkConstraints": {}
},
"public.users": {
"users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"type": "numeric",
"primaryKey": true,
"notNull": true
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
"notNull": true,
"autoincrement": false
},
"avatar": {
"name": "avatar",
"type": "text",
"primaryKey": false,
"notNull": true
"notNull": false,
"autoincrement": false
},
"city": {
"name": "city",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"country": {
"name": "country",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"sex": {
"name": "sex",
"type": "text",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"weight": {
"name": "weight",
"type": "numeric",
"type": "integer",
"primaryKey": false,
"notNull": false
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"type": "integer",
"primaryKey": false,
"notNull": true,
"default": "now()"
"autoincrement": false
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
"checkConstraints": {}
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"enums": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
}

View File

@@ -1,216 +0,0 @@
{
"id": "912c6e36-57b1-4e7f-a29b-586b187b1c32",
"prevId": "c8519a52-b999-48f3-b532-42a5678e3905",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.preferences": {
"name": "preferences",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "preferences_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"preferences_user_id_users_id_fk": {
"name": "preferences_user_id_users_id_fk",
"tableFrom": "preferences",
"tableTo": "users",
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"preferences_user_id_unique": {
"name": "preferences_user_id_unique",
"nullsNotDistinct": false,
"columns": ["user_id"]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tokens": {
"name": "tokens",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "tokens_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"tokens_user_id_users_id_fk": {
"name": "tokens_user_id_users_id_fk",
"tableFrom": "tokens",
"tableTo": "users",
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"tokens_user_id_unique": {
"name": "tokens_user_id_unique",
"nullsNotDistinct": false,
"columns": ["user_id"]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"avatar": {
"name": "avatar",
"type": "text",
"primaryKey": false,
"notNull": true
},
"city": {
"name": "city",
"type": "text",
"primaryKey": false,
"notNull": false
},
"country": {
"name": "country",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sex": {
"name": "sex",
"type": "text",
"primaryKey": false,
"notNull": false
},
"premium": {
"name": "premium",
"type": "boolean",
"primaryKey": false,
"notNull": false
},
"weight": {
"name": "weight",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,216 +0,0 @@
{
"id": "7b607167-551b-4aa3-8305-afe3c4d72ace",
"prevId": "912c6e36-57b1-4e7f-a29b-586b187b1c32",
"version": "7",
"dialect": "postgresql",
"tables": {
"public.preferences": {
"name": "preferences",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "preferences_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"data": {
"name": "data",
"type": "jsonb",
"primaryKey": false,
"notNull": false
}
},
"indexes": {},
"foreignKeys": {
"preferences_user_id_users_id_fk": {
"name": "preferences_user_id_users_id_fk",
"tableFrom": "preferences",
"tableTo": "users",
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"preferences_user_id_unique": {
"name": "preferences_user_id_unique",
"nullsNotDistinct": false,
"columns": ["user_id"]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.tokens": {
"name": "tokens",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"identity": {
"type": "always",
"name": "tokens_id_seq",
"schema": "public",
"increment": "1",
"startWith": "1",
"minValue": "1",
"maxValue": "2147483647",
"cache": "1",
"cycle": false
}
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": false
},
"refresh_token": {
"name": "refresh_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"access_token": {
"name": "access_token",
"type": "text",
"primaryKey": false,
"notNull": false
},
"expires_at": {
"name": "expires_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {
"tokens_user_id_users_id_fk": {
"name": "tokens_user_id_users_id_fk",
"tableFrom": "tokens",
"tableTo": "users",
"columnsFrom": ["user_id"],
"columnsTo": ["id"],
"onDelete": "cascade",
"onUpdate": "no action"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {
"tokens_user_id_unique": {
"name": "tokens_user_id_unique",
"nullsNotDistinct": false,
"columns": ["user_id"]
}
},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
},
"public.users": {
"name": "users",
"schema": "",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true
},
"avatar": {
"name": "avatar",
"type": "text",
"primaryKey": false,
"notNull": true
},
"city": {
"name": "city",
"type": "text",
"primaryKey": false,
"notNull": false
},
"country": {
"name": "country",
"type": "text",
"primaryKey": false,
"notNull": false
},
"sex": {
"name": "sex",
"type": "text",
"primaryKey": false,
"notNull": false
},
"premium": {
"name": "premium",
"type": "boolean",
"primaryKey": false,
"notNull": true
},
"weight": {
"name": "weight",
"type": "numeric",
"primaryKey": false,
"notNull": false
},
"created_at": {
"name": "created_at",
"type": "timestamp",
"primaryKey": false,
"notNull": true,
"default": "now()"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"policies": {},
"checkConstraints": {},
"isRLSEnabled": false
}
},
"enums": {},
"schemas": {},
"sequences": {},
"roles": {},
"policies": {},
"views": {},
"_meta": {
"columns": {},
"schemas": {},
"tables": {}
}
}

View File

@@ -1,27 +1,13 @@
{
"version": "7",
"dialect": "postgresql",
"dialect": "sqlite",
"entries": [
{
"idx": 0,
"version": "7",
"when": 1745335305323,
"tag": "0000_slim_blonde_phantom",
"breakpoints": true
},
{
"idx": 1,
"version": "7",
"when": 1747547391071,
"tag": "0001_smooth_jazinda",
"breakpoints": true
},
{
"idx": 2,
"version": "7",
"when": 1747564780270,
"tag": "0002_many_marauders",
"version": "6",
"when": 1772727834477,
"tag": "0000_living_oracle",
"breakpoints": true
}
]
}
}

View File

@@ -1,34 +1,27 @@
import { relations } from "drizzle-orm";
import {
pgTable,
text,
integer,
numeric,
timestamp,
jsonb,
} from "drizzle-orm/pg-core";
import { sqliteTable, text, integer, numeric } from "drizzle-orm/sqlite-core";
export const users = pgTable("users", {
id: integer("id").primaryKey(),
export const users = sqliteTable("users", {
id: numeric("id").primaryKey(),
name: text("name").notNull(),
avatar: text("avatar").notNull(),
avatar: text("avatar"),
city: text("city"),
country: text("country"),
sex: text("sex"),
weight: numeric("weight", {
mode: "number",
}),
createdAt: timestamp("created_at").notNull().defaultNow(),
weight: integer("weight"),
createdAt: integer("created_at", { mode: "timestamp" })
.notNull()
.$defaultFn(() => new Date()),
});
export const preferences = pgTable("preferences", {
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
userId: integer("user_id")
export const preferences = sqliteTable("preferences", {
id: integer("id").primaryKey({ autoIncrement: true }),
userId: numeric("user_id")
.references(() => users.id, {
onDelete: "cascade",
})
.unique(),
data: jsonb("data")
data: text("data", { mode: "json" })
.$type<{
enabled: boolean;
language: string;
@@ -45,19 +38,20 @@ export const preferences = pgTable("preferences", {
})),
});
export const tokens = pgTable("tokens", {
id: integer("id").primaryKey().generatedAlwaysAsIdentity(),
userId: integer("user_id")
export const tokens = sqliteTable("tokens", {
id: integer("id").primaryKey({ autoIncrement: true }),
userId: numeric("user_id")
.references(() => users.id, {
onDelete: "cascade",
})
.unique(),
refreshToken: text("refresh_token"),
accessToken: text("access_token"),
expiresAt: timestamp("expires_at").notNull().defaultNow(),
expiresAt: integer("expires_at", { mode: "timestamp" })
.notNull()
.$defaultFn(() => new Date()),
});
// Define relationships
export const usersRelations = relations(users, ({ one }) => ({
tokens: one(tokens, {
fields: [users.id],
@@ -69,7 +63,7 @@ export const usersRelations = relations(users, ({ one }) => ({
}),
}));
export const referencesRelations = relations(preferences, ({ one }) => ({
export const preferencesRelations = relations(preferences, ({ one }) => ({
user: one(users, {
fields: [preferences.userId],
references: [users.id],

View File

@@ -0,0 +1,12 @@
import { migrate } from "drizzle-orm/bun-sqlite/migrator";
import { drizzle } from "drizzle-orm/bun-sqlite";
import * as schema from "../database/schema";
export default defineNitroPlugin(async () => {
const config = useRuntimeConfig();
const db = drizzle(config.databaseUrl, { schema });
console.log("Running database migrations...");
await migrate(db, { migrationsFolder: "./server/database/migrations" });
console.log("Database migrations complete");
});

View File

@@ -30,7 +30,7 @@ export default defineOAuthStravaEventHandler({
city: auth.user.city,
country: auth.user.country,
sex: auth.user.sex,
weight: auth.user.weight,
// weight: auth.user.weight,
avatar: auth.user.profile,
};

View File

@@ -101,33 +101,16 @@ export const createActivityContent = async ({
: draw(user.preferences.data!.highlights!);
const length = match({ tone })
.with({ tone: "Minimalist" }, () => "short")
.otherwise(() => draw(["short", "medium", "a-little-more-than-medium"]));
.with({ tone: "Minimalist" }, () => "very short")
.otherwise(() => draw(["very short", "short"]));
const prompt = `
Generate a short title and a ${length}-lengthed description for my strava activity. Use my preferred language and unit system.
Use first person, as this will be posting for myself. Try to not exaggerate as I am using Strava often and I want my activites to be unique and easy to read. Don't use repeative language.
Depending the activity conditions and achievements, use one of the following tones to make things less boring:
${availableTones.join(", ")}. Accordingly, depending on the activity's conditions, highlight area exploration, athletic achievements, mood swings or weather conditions.
If there is nothing interesting to say, try making a mild joke or say an interesting fact about the route. Do not add fun facts if mentioned in the recent activities.
Take heart data, suffer score and weather into consideration if available, combine them to understand the effort. No need to mention suffer score every time.
Maybe comment if any interesting fact in comparison to previous activities.
NEVER use — symbol. Not for titles, not for descriptions.
Depending the length of the description, maybe add hashtags.
Language: ${user?.preferences.data!.language}
Unit system: ${user?.preferences.data!.units}
Activity notes:
Distance is in meters, time is in seconds, don't include average speed.
Convert time to hours or minutes, whatever's closer.
Convert distance to larger units when appropriate, we don't need accuracy. Better say almost 50 instead of 48.67 for example.
In the end of the description, add "${promo}" translated to my language.
Tone: ${tone}
Highlight: ${highlight}
Description length: ${length}
The activity data in json format from strava:
${stringifyActivity({ activity: currentActivity })}

View File

@@ -1,5 +1,10 @@
import { drizzle } from "drizzle-orm/neon-http";
export { sql, eq, and, or } from "drizzle-orm";
import { drizzle } from "drizzle-orm/bun-sqlite";
import { eq as _eq, and as _and, or as _or, sql as _sql } from "drizzle-orm";
export const sql = _sql;
export const eq = _eq;
export const and = _and;
export const or = _or;
import * as schema from "../database/schema";