diff options
Diffstat (limited to 'packages/cloud/core/src')
20 files changed, 0 insertions, 913 deletions
diff --git a/packages/cloud/core/src/account.ts b/packages/cloud/core/src/account.ts deleted file mode 100644 index cb123e048..000000000 --- a/packages/cloud/core/src/account.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { z } from "zod" -import { and, eq, getTableColumns, isNull } from "drizzle-orm" -import { fn } from "./util/fn" -import { Database } from "./drizzle" -import { Identifier } from "./identifier" -import { AccountTable } from "./schema/account.sql" -import { Actor } from "./actor" -import { WorkspaceTable } from "./schema/workspace.sql" -import { UserTable } from "./schema/user.sql" - -export namespace Account { - export const create = fn( - z.object({ - email: z.string().email(), - id: z.string().optional(), - }), - async (input) => - Database.transaction(async (tx) => { - const id = input.id ?? Identifier.create("account") - await tx.insert(AccountTable).values({ - id, - email: input.email, - }) - return id - }), - ) - - export const fromID = fn(z.string(), async (id) => - Database.transaction(async (tx) => { - return tx - .select() - .from(AccountTable) - .where(eq(AccountTable.id, id)) - .execute() - .then((rows) => rows[0]) - }), - ) - - export const fromEmail = fn(z.string().email(), async (email) => - Database.transaction(async (tx) => { - return tx - .select() - .from(AccountTable) - .where(eq(AccountTable.email, email)) - .execute() - .then((rows) => rows[0]) - }), - ) - - export const workspaces = async () => { - const actor = Actor.assert("account") - return Database.transaction(async (tx) => - tx - .select(getTableColumns(WorkspaceTable)) - .from(WorkspaceTable) - .innerJoin(UserTable, eq(UserTable.workspaceID, WorkspaceTable.id)) - .where( - and( - eq(UserTable.email, actor.properties.email), - isNull(UserTable.timeDeleted), - isNull(WorkspaceTable.timeDeleted), - ), - ) - .execute(), - ) - } -} diff --git a/packages/cloud/core/src/actor.ts b/packages/cloud/core/src/actor.ts deleted file mode 100644 index 0d13f7216..000000000 --- a/packages/cloud/core/src/actor.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { Context } from "./context" -import { Log } from "./util/log" - -export namespace Actor { - interface Account { - type: "account" - properties: { - accountID: string - email: string - } - } - - interface Public { - type: "public" - properties: {} - } - - interface User { - type: "user" - properties: { - userID: string - workspaceID: string - } - } - - interface System { - type: "system" - properties: { - workspaceID: string - } - } - - export type Info = Account | Public | User | System - - const ctx = Context.create<Info>() - export const use = ctx.use - - const log = Log.create().tag("namespace", "actor") - - export function provide<R, T extends Info["type"]>( - type: T, - properties: Extract<Info, { type: T }>["properties"], - cb: () => R, - ) { - return ctx.provide( - { - type, - properties, - } as any, - () => { - return Log.provide({ ...properties }, () => { - log.info("provided") - return cb() - }) - }, - ) - } - - export function assert<T extends Info["type"]>(type: T) { - const actor = use() - if (actor.type !== type) { - throw new Error(`Expected actor type ${type}, got ${actor.type}`) - } - return actor as Extract<Info, { type: T }> - } - - export function workspace() { - const actor = use() - if ("workspaceID" in actor.properties) { - return actor.properties.workspaceID - } - throw new Error(`actor of type "${actor.type}" is not associated with a workspace`) - } -} diff --git a/packages/cloud/core/src/billing.ts b/packages/cloud/core/src/billing.ts deleted file mode 100644 index 2254adc79..000000000 --- a/packages/cloud/core/src/billing.ts +++ /dev/null @@ -1,244 +0,0 @@ -import { Stripe } from "stripe" -import { Database, eq, sql } from "./drizzle" -import { BillingTable, PaymentTable, UsageTable } from "./schema/billing.sql" -import { Actor } from "./actor" -import { fn } from "./util/fn" -import { z } from "zod" -import { User } from "./user" -import { Resource } from "@opencode/cloud-resource" -import { Identifier } from "./identifier" -import { centsToMicroCents } from "./util/price" - -export namespace Billing { - export const CHARGE_AMOUNT = 2000 // $20 - export const CHARGE_FEE = 123 // Stripe fee 4.4% + $0.30 - export const CHARGE_THRESHOLD = 500 // $5 - export const stripe = () => - new Stripe(Resource.STRIPE_SECRET_KEY.value, { - apiVersion: "2025-03-31.basil", - }) - - export const get = async () => { - return Database.use(async (tx) => - tx - .select({ - customerID: BillingTable.customerID, - paymentMethodID: BillingTable.paymentMethodID, - paymentMethodLast4: BillingTable.paymentMethodLast4, - balance: BillingTable.balance, - reload: BillingTable.reload, - monthlyLimit: BillingTable.monthlyLimit, - monthlyUsage: BillingTable.monthlyUsage, - timeMonthlyUsageUpdated: BillingTable.timeMonthlyUsageUpdated, - reloadError: BillingTable.reloadError, - timeReloadError: BillingTable.timeReloadError, - }) - .from(BillingTable) - .where(eq(BillingTable.workspaceID, Actor.workspace())) - .then((r) => r[0]), - ) - } - - export const payments = async () => { - return await Database.use((tx) => - tx - .select() - .from(PaymentTable) - .where(eq(PaymentTable.workspaceID, Actor.workspace())) - .orderBy(sql`${PaymentTable.timeCreated} DESC`) - .limit(100), - ) - } - - export const usages = async () => { - return await Database.use((tx) => - tx - .select() - .from(UsageTable) - .where(eq(UsageTable.workspaceID, Actor.workspace())) - .orderBy(sql`${UsageTable.timeCreated} DESC`) - .limit(100), - ) - } - - export const reload = async () => { - const { customerID, paymentMethodID } = await Database.use((tx) => - tx - .select({ - customerID: BillingTable.customerID, - paymentMethodID: BillingTable.paymentMethodID, - }) - .from(BillingTable) - .where(eq(BillingTable.workspaceID, Actor.workspace())) - .then((rows) => rows[0]), - ) - const paymentID = Identifier.create("payment") - let charge - try { - charge = await Billing.stripe().paymentIntents.create( - { - amount: Billing.CHARGE_AMOUNT + Billing.CHARGE_FEE, - currency: "usd", - customer: customerID!, - payment_method: paymentMethodID!, - off_session: true, - confirm: true, - }, - { idempotencyKey: paymentID }, - ) - - if (charge.status !== "succeeded") throw new Error(charge.last_payment_error?.message) - } catch (e: any) { - await Database.use((tx) => - tx - .update(BillingTable) - .set({ - reloadError: e.message ?? "Payment failed.", - timeReloadError: sql`now()`, - }) - .where(eq(BillingTable.workspaceID, Actor.workspace())), - ) - return - } - - await Database.transaction(async (tx) => { - await tx - .update(BillingTable) - .set({ - balance: sql`${BillingTable.balance} + ${centsToMicroCents(CHARGE_AMOUNT)}`, - reloadError: null, - timeReloadError: null, - }) - .where(eq(BillingTable.workspaceID, Actor.workspace())) - await tx.insert(PaymentTable).values({ - workspaceID: Actor.workspace(), - id: paymentID, - amount: centsToMicroCents(CHARGE_AMOUNT), - paymentID: charge.id, - customerID, - }) - }) - } - - export const disableReload = async () => { - return await Database.use((tx) => - tx - .update(BillingTable) - .set({ - reload: false, - }) - .where(eq(BillingTable.workspaceID, Actor.workspace())), - ) - } - - export const setMonthlyLimit = fn(z.number(), async (input) => { - return await Database.use((tx) => - tx - .update(BillingTable) - .set({ - monthlyLimit: input, - }) - .where(eq(BillingTable.workspaceID, Actor.workspace())), - ) - }) - - export const generateCheckoutUrl = fn( - z.object({ - successUrl: z.string(), - cancelUrl: z.string(), - }), - async (input) => { - const account = Actor.assert("user") - const { successUrl, cancelUrl } = input - - const user = await User.fromID(account.properties.userID) - const customer = await Billing.get() - const session = await Billing.stripe().checkout.sessions.create({ - mode: "payment", - line_items: [ - { - price_data: { - currency: "usd", - product_data: { - name: "opencode credits", - }, - unit_amount: CHARGE_AMOUNT, - }, - quantity: 1, - }, - { - price_data: { - currency: "usd", - product_data: { - name: "processing fee", - }, - unit_amount: CHARGE_FEE, - }, - quantity: 1, - }, - ], - payment_intent_data: { - setup_future_usage: "on_session", - }, - ...(customer.customerID - ? { - customer: customer.customerID, - } - : { - customer_email: user.email, - customer_creation: "always", - }), - metadata: { - workspaceID: Actor.workspace(), - }, - currency: "usd", - payment_method_types: ["card"], - payment_method_data: { - allow_redisplay: "always", - }, - success_url: successUrl, - cancel_url: cancelUrl, - }) - - return session.url - }, - ) - - export const generateSessionUrl = fn( - z.object({ - returnUrl: z.string(), - }), - async (input) => { - const { returnUrl } = input - - const customer = await Billing.get() - if (!customer?.customerID) { - throw new Error("No stripe customer ID") - } - - const session = await Billing.stripe().billingPortal.sessions.create({ - customer: customer.customerID, - return_url: returnUrl, - }) - - return session.url - }, - ) - - export const generateReceiptUrl = fn( - z.object({ - paymentID: z.string(), - }), - async (input) => { - const { paymentID } = input - - const intent = await Billing.stripe().paymentIntents.retrieve(paymentID) - if (!intent.latest_charge) throw new Error("No charge found") - - const charge = await Billing.stripe().charges.retrieve(intent.latest_charge as string) - if (!charge.receipt_url) throw new Error("No receipt URL found") - - return charge.receipt_url - }, - ) -} diff --git a/packages/cloud/core/src/context.ts b/packages/cloud/core/src/context.ts deleted file mode 100644 index c2ca6a313..000000000 --- a/packages/cloud/core/src/context.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { AsyncLocalStorage } from "node:async_hooks" - -export namespace Context { - export class NotFound extends Error {} - - export function create<T>() { - const storage = new AsyncLocalStorage<T>() - return { - use() { - const result = storage.getStore() - if (!result) { - throw new NotFound() - } - return result - }, - provide<R>(value: T, fn: () => R) { - return storage.run<R>(value, fn) - }, - } - } -} diff --git a/packages/cloud/core/src/drizzle/index.ts b/packages/cloud/core/src/drizzle/index.ts deleted file mode 100644 index 806037996..000000000 --- a/packages/cloud/core/src/drizzle/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { drizzle } from "drizzle-orm/planetscale-serverless" -import { Resource } from "@opencode/cloud-resource" -export * from "drizzle-orm" -import { Client } from "@planetscale/database" - -import { MySqlTransaction, type MySqlTransactionConfig } from "drizzle-orm/mysql-core" -import type { ExtractTablesWithRelations } from "drizzle-orm" -import type { PlanetScalePreparedQueryHKT, PlanetscaleQueryResultHKT } from "drizzle-orm/planetscale-serverless" -import { Context } from "../context" -import { memo } from "../util/memo" - -export namespace Database { - export type Transaction = MySqlTransaction< - PlanetscaleQueryResultHKT, - PlanetScalePreparedQueryHKT, - Record<string, never>, - ExtractTablesWithRelations<Record<string, never>> - > - - const client = memo(() => { - const result = new Client({ - host: Resource.Database.host, - username: Resource.Database.username, - password: Resource.Database.password, - }) - const db = drizzle(result, {}) - return db - }) - - export type TxOrDb = Transaction | ReturnType<typeof client> - - const TransactionContext = Context.create<{ - tx: TxOrDb - effects: (() => void | Promise<void>)[] - }>() - - export async function use<T>(callback: (trx: TxOrDb) => Promise<T>) { - try { - const { tx } = TransactionContext.use() - return tx.transaction(callback) - } catch (err) { - if (err instanceof Context.NotFound) { - const effects: (() => void | Promise<void>)[] = [] - const result = await TransactionContext.provide( - { - effects, - tx: client(), - }, - () => callback(client()), - ) - await Promise.all(effects.map((x) => x())) - return result - } - throw err - } - } - export async function fn<Input, T>(callback: (input: Input, trx: TxOrDb) => Promise<T>) { - return (input: Input) => use(async (tx) => callback(input, tx)) - } - - export async function effect(effect: () => any | Promise<any>) { - try { - const { effects } = TransactionContext.use() - effects.push(effect) - } catch { - await effect() - } - } - - export async function transaction<T>(callback: (tx: TxOrDb) => Promise<T>, config?: MySqlTransactionConfig) { - try { - const { tx } = TransactionContext.use() - return callback(tx) - } catch (err) { - if (err instanceof Context.NotFound) { - const effects: (() => void | Promise<void>)[] = [] - const result = await client().transaction(async (tx) => { - return TransactionContext.provide({ tx, effects }, () => callback(tx)) - }, config) - await Promise.all(effects.map((x) => x())) - return result - } - throw err - } - } -} diff --git a/packages/cloud/core/src/drizzle/types.ts b/packages/cloud/core/src/drizzle/types.ts deleted file mode 100644 index f16ad5a8a..000000000 --- a/packages/cloud/core/src/drizzle/types.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { sql } from "drizzle-orm" -import { bigint, timestamp, varchar } from "drizzle-orm/mysql-core" - -export const ulid = (name: string) => varchar(name, { length: 30 }) - -export const workspaceColumns = { - get id() { - return ulid("id").notNull() - }, - get workspaceID() { - return ulid("workspace_id").notNull() - }, -} - -export const id = () => ulid("id").notNull() - -export const utc = (name: string) => - timestamp(name, { - fsp: 3, - }) - -export const currency = (name: string) => - bigint(name, { - mode: "number", - }) - -export const timestamps = { - timeCreated: utc("time_created").notNull().defaultNow(), - timeUpdated: utc("time_updated") - .notNull() - .default(sql`CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)`), - timeDeleted: utc("time_deleted"), -} diff --git a/packages/cloud/core/src/identifier.ts b/packages/cloud/core/src/identifier.ts deleted file mode 100644 index f8e73852e..000000000 --- a/packages/cloud/core/src/identifier.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { ulid } from "ulid" -import { z } from "zod" - -export namespace Identifier { - const prefixes = { - account: "acc", - billing: "bil", - key: "key", - payment: "pay", - usage: "usg", - user: "usr", - workspace: "wrk", - } as const - - export function create(prefix: keyof typeof prefixes, given?: string): string { - if (given) { - if (given.startsWith(prefixes[prefix])) return given - throw new Error(`ID ${given} does not start with ${prefixes[prefix]}`) - } - return [prefixes[prefix], ulid()].join("_") - } - - export function schema(prefix: keyof typeof prefixes) { - return z.string().startsWith(prefixes[prefix]) - } -} diff --git a/packages/cloud/core/src/key.ts b/packages/cloud/core/src/key.ts deleted file mode 100644 index 28643a521..000000000 --- a/packages/cloud/core/src/key.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { z } from "zod" -import { fn } from "./util/fn" -import { Actor } from "./actor" -import { and, Database, eq, isNull, sql } from "./drizzle" -import { Identifier } from "./identifier" -import { KeyTable } from "./schema/key.sql" - -export namespace Key { - export const list = async () => { - const workspace = Actor.workspace() - const keys = await Database.use((tx) => - tx - .select() - .from(KeyTable) - .where(and(eq(KeyTable.workspaceID, workspace), isNull(KeyTable.timeDeleted))) - .orderBy(sql`${KeyTable.timeCreated} DESC`), - ) - return keys - } - - export const create = fn(z.object({ name: z.string().min(1).max(255) }), async (input) => { - const workspaceID = Actor.workspace() - const { name } = input - - // Generate secret key: sk- + 64 random characters (upper, lower, numbers) - const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" - let secretKey = "sk-" - const array = new Uint32Array(64) - crypto.getRandomValues(array) - for (let i = 0, l = array.length; i < l; i++) { - secretKey += chars[array[i] % chars.length] - } - const keyID = Identifier.create("key") - - await Database.use((tx) => - tx.insert(KeyTable).values({ - id: keyID, - workspaceID, - actor: Actor.use(), - name, - key: secretKey, - timeUsed: null, - }), - ).catch((e: any) => { - if (e.message.match(/Duplicate entry '.*' for key 'key.name'/)) - throw new Error("A key with this name already exists. Please choose a different name.") - throw e - }) - - return keyID - }) - - export const remove = fn(z.object({ id: z.string() }), async (input) => { - const workspace = Actor.workspace() - await Database.transaction(async (tx) => { - const row = await tx - .select({ - name: KeyTable.name, - }) - .from(KeyTable) - .where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace))) - .then((rows) => rows[0]) - if (!row) return - - await tx - .update(KeyTable) - .set({ - timeDeleted: sql`now()`, - oldName: row.name, - name: input.id, // Use the key ID as the name - }) - .where(and(eq(KeyTable.id, input.id), eq(KeyTable.workspaceID, workspace))) - }) - }) -} diff --git a/packages/cloud/core/src/schema/account.sql.ts b/packages/cloud/core/src/schema/account.sql.ts deleted file mode 100644 index 4d9937114..000000000 --- a/packages/cloud/core/src/schema/account.sql.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core" -import { id, timestamps } from "../drizzle/types" - -export const AccountTable = mysqlTable( - "account", - { - id: id(), - ...timestamps, - email: varchar("email", { length: 255 }).notNull(), - }, - (table) => [uniqueIndex("email").on(table.email)], -) diff --git a/packages/cloud/core/src/schema/billing.sql.ts b/packages/cloud/core/src/schema/billing.sql.ts deleted file mode 100644 index 5bec4e900..000000000 --- a/packages/cloud/core/src/schema/billing.sql.ts +++ /dev/null @@ -1,53 +0,0 @@ -import { bigint, boolean, int, mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core" -import { timestamps, utc, workspaceColumns } from "../drizzle/types" -import { workspaceIndexes } from "./workspace.sql" - -export const BillingTable = mysqlTable( - "billing", - { - ...workspaceColumns, - ...timestamps, - customerID: varchar("customer_id", { length: 255 }), - paymentMethodID: varchar("payment_method_id", { length: 255 }), - paymentMethodLast4: varchar("payment_method_last4", { length: 4 }), - balance: bigint("balance", { mode: "number" }).notNull(), - monthlyLimit: int("monthly_limit"), - monthlyUsage: bigint("monthly_usage", { mode: "number" }), - timeMonthlyUsageUpdated: utc("time_monthly_usage_updated"), - reload: boolean("reload"), - reloadError: varchar("reload_error", { length: 255 }), - timeReloadError: utc("time_reload_error"), - timeReloadLockedTill: utc("time_reload_locked_till"), - }, - (table) => [...workspaceIndexes(table), uniqueIndex("global_customer_id").on(table.customerID)], -) - -export const PaymentTable = mysqlTable( - "payment", - { - ...workspaceColumns, - ...timestamps, - customerID: varchar("customer_id", { length: 255 }), - paymentID: varchar("payment_id", { length: 255 }), - amount: bigint("amount", { mode: "number" }).notNull(), - }, - (table) => [...workspaceIndexes(table)], -) - -export const UsageTable = mysqlTable( - "usage", - { - ...workspaceColumns, - ...timestamps, - model: varchar("model", { length: 255 }).notNull(), - provider: varchar("provider", { length: 255 }).notNull(), - inputTokens: int("input_tokens").notNull(), - outputTokens: int("output_tokens").notNull(), - reasoningTokens: int("reasoning_tokens"), - cacheReadTokens: int("cache_read_tokens"), - cacheWrite5mTokens: int("cache_write_5m_tokens"), - cacheWrite1hTokens: int("cache_write_1h_tokens"), - cost: bigint("cost", { mode: "number" }).notNull(), - }, - (table) => [...workspaceIndexes(table)], -) diff --git a/packages/cloud/core/src/schema/key.sql.ts b/packages/cloud/core/src/schema/key.sql.ts deleted file mode 100644 index 98b99c788..000000000 --- a/packages/cloud/core/src/schema/key.sql.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { mysqlTable, varchar, uniqueIndex, json } from "drizzle-orm/mysql-core" -import { timestamps, utc, workspaceColumns } from "../drizzle/types" -import { workspaceIndexes } from "./workspace.sql" -import { Actor } from "../actor" - -export const KeyTable = mysqlTable( - "key", - { - ...workspaceColumns, - ...timestamps, - actor: json("actor").$type<Actor.Info>(), - name: varchar("name", { length: 255 }).notNull(), - oldName: varchar("old_name", { length: 255 }), - key: varchar("key", { length: 255 }).notNull(), - timeUsed: utc("time_used"), - }, - (table) => [ - ...workspaceIndexes(table), - uniqueIndex("global_key").on(table.key), - uniqueIndex("name").on(table.workspaceID, table.name), - ], -) diff --git a/packages/cloud/core/src/schema/user.sql.ts b/packages/cloud/core/src/schema/user.sql.ts deleted file mode 100644 index 00c372d1a..000000000 --- a/packages/cloud/core/src/schema/user.sql.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { text, mysqlTable, uniqueIndex, varchar, int } from "drizzle-orm/mysql-core" -import { timestamps, utc, workspaceColumns } from "../drizzle/types" -import { workspaceIndexes } from "./workspace.sql" - -export const UserTable = mysqlTable( - "user", - { - ...workspaceColumns, - ...timestamps, - email: varchar("email", { length: 255 }).notNull(), - name: varchar("name", { length: 255 }).notNull(), - timeSeen: utc("time_seen"), - color: int("color"), - }, - (table) => [...workspaceIndexes(table), uniqueIndex("user_email").on(table.workspaceID, table.email)], -) diff --git a/packages/cloud/core/src/schema/workspace.sql.ts b/packages/cloud/core/src/schema/workspace.sql.ts deleted file mode 100644 index 979255428..000000000 --- a/packages/cloud/core/src/schema/workspace.sql.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { primaryKey, mysqlTable, uniqueIndex, varchar } from "drizzle-orm/mysql-core" -import { timestamps, ulid } from "../drizzle/types" - -export const WorkspaceTable = mysqlTable( - "workspace", - { - id: ulid("id").notNull().primaryKey(), - slug: varchar("slug", { length: 255 }), - name: varchar("name", { length: 255 }), - ...timestamps, - }, - (table) => [uniqueIndex("slug").on(table.slug)], -) - -export function workspaceIndexes(table: any) { - return [ - primaryKey({ - columns: [table.workspaceID, table.id], - }), - ] -} diff --git a/packages/cloud/core/src/user.ts b/packages/cloud/core/src/user.ts deleted file mode 100644 index 7914926ff..000000000 --- a/packages/cloud/core/src/user.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { z } from "zod" -import { eq } from "drizzle-orm" -import { fn } from "./util/fn" -import { Database } from "./drizzle" -import { UserTable } from "./schema/user.sql" - -export namespace User { - export const fromID = fn(z.string(), async (id) => - Database.transaction(async (tx) => { - return tx - .select() - .from(UserTable) - .where(eq(UserTable.id, id)) - .execute() - .then((rows) => rows[0]) - }), - ) -} diff --git a/packages/cloud/core/src/util/env.cloudflare.ts b/packages/cloud/core/src/util/env.cloudflare.ts deleted file mode 100644 index e69de29bb..000000000 --- a/packages/cloud/core/src/util/env.cloudflare.ts +++ /dev/null diff --git a/packages/cloud/core/src/util/fn.ts b/packages/cloud/core/src/util/fn.ts deleted file mode 100644 index 9efe4622f..000000000 --- a/packages/cloud/core/src/util/fn.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { z } from "zod" - -export function fn<T extends z.ZodType, Result>(schema: T, cb: (input: z.infer<T>) => Result) { - const result = (input: z.infer<T>) => { - const parsed = schema.parse(input) - return cb(parsed) - } - result.force = (input: z.infer<T>) => cb(input) - result.schema = schema - return result -} diff --git a/packages/cloud/core/src/util/log.ts b/packages/cloud/core/src/util/log.ts deleted file mode 100644 index 4f2d25c13..000000000 --- a/packages/cloud/core/src/util/log.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { Context } from "../context" - -export namespace Log { - const ctx = Context.create<{ - tags: Record<string, any> - }>() - - export function create(tags?: Record<string, any>) { - tags = tags || {} - - const result = { - info(message?: any, extra?: Record<string, any>) { - const prefix = Object.entries({ - ...use().tags, - ...tags, - ...extra, - }) - .map(([key, value]) => `${key}=${value}`) - .join(" ") - console.log(prefix, message) - return result - }, - tag(key: string, value: string) { - if (tags) tags[key] = value - return result - }, - clone() { - return Log.create({ ...tags }) - }, - } - - return result - } - - export function provide<R>(tags: Record<string, any>, cb: () => R) { - const existing = use() - return ctx.provide( - { - tags: { - ...existing.tags, - ...tags, - }, - }, - cb, - ) - } - - function use() { - try { - return ctx.use() - } catch (e) { - return { tags: {} } - } - } -} diff --git a/packages/cloud/core/src/util/memo.ts b/packages/cloud/core/src/util/memo.ts deleted file mode 100644 index 49043010f..000000000 --- a/packages/cloud/core/src/util/memo.ts +++ /dev/null @@ -1,18 +0,0 @@ -export function memo<T>(fn: () => T, cleanup?: (input: T) => Promise<void>) { - let value: T | undefined - let loaded = false - - const result = (): T => { - if (loaded) return value as T - loaded = true - value = fn() - return value as T - } - result.reset = async () => { - if (cleanup && value) await cleanup(value) - loaded = false - value = undefined - } - - return result -} diff --git a/packages/cloud/core/src/util/price.ts b/packages/cloud/core/src/util/price.ts deleted file mode 100644 index abdbca032..000000000 --- a/packages/cloud/core/src/util/price.ts +++ /dev/null @@ -1,3 +0,0 @@ -export function centsToMicroCents(amount: number) { - return Math.round(amount * 1000000) -} diff --git a/packages/cloud/core/src/workspace.ts b/packages/cloud/core/src/workspace.ts deleted file mode 100644 index a9fb923d6..000000000 --- a/packages/cloud/core/src/workspace.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { z } from "zod" -import { fn } from "./util/fn" -import { centsToMicroCents } from "./util/price" -import { Actor } from "./actor" -import { Database, eq } from "./drizzle" -import { Identifier } from "./identifier" -import { UserTable } from "./schema/user.sql" -import { BillingTable } from "./schema/billing.sql" -import { WorkspaceTable } from "./schema/workspace.sql" -import { Key } from "./key" - -export namespace Workspace { - export const create = fn(z.void(), async () => { - const account = Actor.assert("account") - const workspaceID = Identifier.create("workspace") - await Database.transaction(async (tx) => { - await tx.insert(WorkspaceTable).values({ - id: workspaceID, - }) - await tx.insert(UserTable).values({ - workspaceID, - id: Identifier.create("user"), - email: account.properties.email, - name: "", - }) - await tx.insert(BillingTable).values({ - workspaceID, - id: Identifier.create("billing"), - balance: 0, - }) - }) - await Actor.provide( - "system", - { - workspaceID, - }, - async () => { - await Key.create({ name: "Default API Key" }) - }, - ) - return workspaceID - }) - - export async function list() { - const account = Actor.assert("account") - return Database.use(async (tx) => { - return tx - .select({ - id: WorkspaceTable.id, - slug: WorkspaceTable.slug, - name: WorkspaceTable.name, - }) - .from(UserTable) - .innerJoin(WorkspaceTable, eq(UserTable.workspaceID, WorkspaceTable.id)) - .where(eq(UserTable.email, account.properties.email)) - }) - } -} |
