lookup-user.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. import { Database, eq, sql, inArray } from "../src/drizzle/index.js"
  2. import { AuthTable } from "../src/schema/auth.sql.js"
  3. import { UserTable } from "../src/schema/user.sql.js"
  4. import { BillingTable, PaymentTable } from "../src/schema/billing.sql.js"
  5. import { WorkspaceTable } from "../src/schema/workspace.sql.js"
  6. // get input from command line
  7. const identifier = process.argv[2]
  8. if (!identifier) {
  9. console.error("Usage: bun lookup-user.ts <email|workspaceID>")
  10. process.exit(1)
  11. }
  12. if (identifier.startsWith("wrk_")) {
  13. await printWorkspace(identifier)
  14. } else {
  15. const authData = await printTable("Email", (tx) =>
  16. tx.select().from(AuthTable).where(eq(AuthTable.subject, identifier)),
  17. )
  18. if (authData.length === 0) {
  19. console.error("Email not found")
  20. process.exit(1)
  21. }
  22. if (authData.length > 1) console.warn("Multiple users found for email", identifier)
  23. // Get all auth records for email
  24. const accountID = authData[0].accountID
  25. await printTable("Auth Records", (tx) => tx.select().from(AuthTable).where(eq(AuthTable.accountID, accountID)))
  26. // Get all workspaces for this account
  27. const users = await printTable("Workspaces", (tx) =>
  28. tx
  29. .select({
  30. userID: UserTable.id,
  31. workspaceID: UserTable.workspaceID,
  32. workspaceName: WorkspaceTable.name,
  33. role: UserTable.role,
  34. })
  35. .from(UserTable)
  36. .innerJoin(WorkspaceTable, eq(WorkspaceTable.id, UserTable.workspaceID))
  37. .where(eq(UserTable.accountID, accountID)),
  38. )
  39. // Get all payments for these workspaces
  40. await Promise.all(users.map((u: { workspaceID: string }) => printWorkspace(u.workspaceID)))
  41. }
  42. async function printWorkspace(workspaceID: string) {
  43. const workspace = await Database.use((tx) =>
  44. tx
  45. .select()
  46. .from(WorkspaceTable)
  47. .where(eq(WorkspaceTable.id, workspaceID))
  48. .then((rows) => rows[0]),
  49. )
  50. printHeader(`Workspace "${workspace.name}" (${workspace.id})`)
  51. await printTable("Billing", (tx) =>
  52. tx
  53. .select({
  54. balance: BillingTable.balance,
  55. })
  56. .from(BillingTable)
  57. .where(eq(BillingTable.workspaceID, workspace.id))
  58. .then(
  59. (rows) =>
  60. rows.map((row) => ({
  61. ...row,
  62. balance: `$${(row.balance / 100000000).toFixed(2)}`,
  63. }))[0],
  64. ),
  65. )
  66. await printTable("Payments", (tx) =>
  67. tx
  68. .select({
  69. amount: PaymentTable.amount,
  70. paymentID: PaymentTable.paymentID,
  71. invoiceID: PaymentTable.invoiceID,
  72. timeCreated: PaymentTable.timeCreated,
  73. timeRefunded: PaymentTable.timeRefunded,
  74. })
  75. .from(PaymentTable)
  76. .where(eq(PaymentTable.workspaceID, workspace.id))
  77. .orderBy(sql`${PaymentTable.timeCreated} DESC`)
  78. .limit(100)
  79. .then((rows) =>
  80. rows.map((row) => ({
  81. ...row,
  82. amount: `$${(row.amount / 100000000).toFixed(2)}`,
  83. paymentID: row.paymentID
  84. ? `https://dashboard.stripe.com/acct_1RszBH2StuRr0lbX/payments/${row.paymentID}`
  85. : null,
  86. })),
  87. ),
  88. )
  89. }
  90. function printHeader(title: string) {
  91. console.log()
  92. console.log("─".repeat(title.length))
  93. console.log(`${title}`)
  94. console.log("─".repeat(title.length))
  95. }
  96. function printTable(title: string, callback: (tx: Database.TxOrDb) => Promise<any>): Promise<any> {
  97. return Database.use(async (tx) => {
  98. const data = await callback(tx)
  99. console.log(`\n== ${title} ==`)
  100. if (data.length === 0) {
  101. console.log("(no data)")
  102. } else {
  103. console.table(data)
  104. }
  105. return data
  106. })
  107. }