appos 0.3.2-0 → 0.3.3-0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/bin/auth-schema-CcqAJY9P.mjs +2 -0
  2. package/dist/bin/better-sqlite3-CuQ3hsWl.mjs +2 -0
  3. package/dist/bin/bun-sql-DGeo-s_M.mjs +2 -0
  4. package/dist/bin/cache-3oO07miM.mjs +2 -0
  5. package/dist/bin/chunk-l9p7A9gZ.mjs +2 -0
  6. package/dist/bin/cockroach-BaICwY7N.mjs +2 -0
  7. package/dist/bin/database-CaysWPpa.mjs +2 -0
  8. package/dist/bin/esm-BvsccvmM.mjs +2 -0
  9. package/dist/bin/esm-CGKzJ7Am.mjs +3 -0
  10. package/dist/bin/event-DnSe3eh0.mjs +8 -0
  11. package/dist/bin/extract-blob-metadata-iqwTl2ft.mjs +170 -0
  12. package/dist/bin/generate-image-variant-Lyx0vhM6.mjs +2 -0
  13. package/dist/bin/generate-preview-0MrKxslA.mjs +2 -0
  14. package/dist/bin/libsql-DQJrZsU9.mjs +2 -0
  15. package/dist/bin/logger-BAGZLUzj.mjs +2 -0
  16. package/dist/bin/main.mjs +1201 -190
  17. package/dist/bin/migrator-B7iNKM8N.mjs +2 -0
  18. package/dist/bin/migrator-BKE1cSQQ.mjs +2 -0
  19. package/dist/bin/migrator-BXcbc9zs.mjs +2 -0
  20. package/dist/bin/migrator-B_XhRWZC.mjs +8 -0
  21. package/dist/bin/migrator-Bz52Gtr8.mjs +2 -0
  22. package/dist/bin/migrator-C7W-cZHB.mjs +2 -0
  23. package/dist/bin/migrator-CEnKyGSW.mjs +2 -0
  24. package/dist/bin/migrator-CHzIIl5X.mjs +2 -0
  25. package/dist/bin/migrator-CR-rjZdM.mjs +2 -0
  26. package/dist/bin/migrator-CjIr1ZCx.mjs +8 -0
  27. package/dist/bin/migrator-Cuubh2dg.mjs +2 -0
  28. package/dist/bin/migrator-D8m-ORbr.mjs +8 -0
  29. package/dist/bin/migrator-DBFwrhZH.mjs +2 -0
  30. package/dist/bin/migrator-DLmhW9u_.mjs +2 -0
  31. package/dist/bin/migrator-DLoHx807.mjs +4 -0
  32. package/dist/bin/migrator-DtN_iS87.mjs +2 -0
  33. package/dist/bin/migrator-Yc57lb3w.mjs +2 -0
  34. package/dist/bin/migrator-cEVXH3xC.mjs +2 -0
  35. package/dist/bin/migrator-hWi-sYIq.mjs +2 -0
  36. package/dist/bin/mysql2-DufFWkj4.mjs +2 -0
  37. package/dist/bin/neon-serverless-5a4h2VFz.mjs +2 -0
  38. package/dist/bin/node-CiOp4xrR.mjs +22 -0
  39. package/dist/bin/node-mssql-DvZGaUkB.mjs +322 -0
  40. package/dist/bin/node-postgres-BqbJVBQY.mjs +2 -0
  41. package/dist/bin/node-postgres-DnhRTTO8.mjs +2 -0
  42. package/dist/bin/open-0ksnL0S8.mjs +2 -0
  43. package/dist/bin/pdf-sUYeFPr4.mjs +14 -0
  44. package/dist/bin/pg-CaH8ptj-.mjs +2 -0
  45. package/dist/bin/pg-core-BLTZt9AH.mjs +8 -0
  46. package/dist/bin/pg-core-CGzidKaA.mjs +2 -0
  47. package/dist/bin/pglite-BJB9z7Ju.mjs +2 -0
  48. package/dist/bin/planetscale-serverless-H3RfLlMK.mjs +13 -0
  49. package/dist/bin/postgres-js-DuOf1eWm.mjs +2 -0
  50. package/dist/bin/purge-attachment-DQXpTtTx.mjs +2 -0
  51. package/dist/bin/purge-audit-logs-BEt2J2gD.mjs +2 -0
  52. package/dist/bin/{purge-unattached-blobs-Duvv8Izd.mjs → purge-unattached-blobs-DOmk4ddJ.mjs} +1 -1
  53. package/dist/bin/query-builder-DSRrR6X_.mjs +8 -0
  54. package/dist/bin/query-builder-V8-LDhvA.mjs +3 -0
  55. package/dist/bin/session-CdB1A-LB.mjs +14 -0
  56. package/dist/bin/session-Cl2e-_i8.mjs +8 -0
  57. package/dist/bin/singlestore-COft6TlR.mjs +8 -0
  58. package/dist/bin/sql-D-eKV1Dn.mjs +2 -0
  59. package/dist/bin/sqlite-cloud-Co9jOn5G.mjs +2 -0
  60. package/dist/bin/sqlite-proxy-Cpu78gJF.mjs +2 -0
  61. package/dist/bin/src-C-oXmCzx.mjs +6 -0
  62. package/dist/bin/table-3zUpWkMg.mjs +2 -0
  63. package/dist/bin/track-db-changes-DWyY5jXm.mjs +2 -0
  64. package/dist/bin/utils-CyoeCJlf.mjs +2 -0
  65. package/dist/bin/utils-EoqYQKy1.mjs +2 -0
  66. package/dist/bin/utils-bsypyqPl.mjs +2 -0
  67. package/dist/bin/vercel-postgres-HWL6xtqi.mjs +2 -0
  68. package/dist/bin/workflow-zxHDyfLq.mjs +2 -0
  69. package/dist/bin/youch-handler-DrYdbUhe.mjs +2 -0
  70. package/dist/bin/zod-MJjkEkRY.mjs +24 -0
  71. package/dist/exports/api/_virtual/rolldown_runtime.mjs +36 -1
  72. package/dist/exports/api/app-context.mjs +24 -1
  73. package/dist/exports/api/auth-schema.mjs +373 -1
  74. package/dist/exports/api/auth.d.mts +4 -0
  75. package/dist/exports/api/auth.mjs +188 -1
  76. package/dist/exports/api/cache.d.mts +2 -2
  77. package/dist/exports/api/cache.mjs +28 -1
  78. package/dist/exports/api/config.mjs +72 -1
  79. package/dist/exports/api/constants.mjs +92 -1
  80. package/dist/exports/api/container.mjs +49 -1
  81. package/dist/exports/api/database.mjs +218 -1
  82. package/dist/exports/api/event.mjs +236 -1
  83. package/dist/exports/api/i18n.mjs +45 -1
  84. package/dist/exports/api/index.mjs +20 -1
  85. package/dist/exports/api/instrumentation.mjs +40 -1
  86. package/dist/exports/api/logger.mjs +26 -1
  87. package/dist/exports/api/mailer.mjs +37 -1
  88. package/dist/exports/api/middleware.mjs +73 -1
  89. package/dist/exports/api/openapi.mjs +507 -1
  90. package/dist/exports/api/orm.mjs +43 -1
  91. package/dist/exports/api/otel.mjs +56 -1
  92. package/dist/exports/api/redis.mjs +41 -1
  93. package/dist/exports/api/storage-schema.mjs +72 -1
  94. package/dist/exports/api/storage.mjs +833 -1
  95. package/dist/exports/api/web/auth.mjs +17 -1
  96. package/dist/exports/api/workflow.mjs +196 -1
  97. package/dist/exports/api/workflows/_virtual/rolldown_runtime.mjs +36 -1
  98. package/dist/exports/api/workflows/api/auth-schema.mjs +373 -1
  99. package/dist/exports/api/workflows/api/auth.d.mts +4 -0
  100. package/dist/exports/api/workflows/api/cache.d.mts +2 -2
  101. package/dist/exports/api/workflows/api/event.mjs +126 -1
  102. package/dist/exports/api/workflows/api/redis.mjs +3 -1
  103. package/dist/exports/api/workflows/api/workflow.mjs +135 -1
  104. package/dist/exports/api/workflows/constants.mjs +23 -1
  105. package/dist/exports/api/workflows/extract-blob-metadata.mjs +132 -1
  106. package/dist/exports/api/workflows/generate-image-variant.d.mts +2 -2
  107. package/dist/exports/api/workflows/generate-image-variant.mjs +118 -1
  108. package/dist/exports/api/workflows/generate-preview.mjs +160 -1
  109. package/dist/exports/api/workflows/index.mjs +3 -1
  110. package/dist/exports/api/workflows/purge-attachment.mjs +34 -1
  111. package/dist/exports/api/workflows/purge-audit-logs.mjs +47 -1
  112. package/dist/exports/api/workflows/purge-unattached-blobs.mjs +46 -1
  113. package/dist/exports/api/workflows/track-db-changes.mjs +110 -1
  114. package/dist/exports/cli/_virtual/rolldown_runtime.mjs +36 -1
  115. package/dist/exports/cli/api/auth-schema.mjs +373 -1
  116. package/dist/exports/cli/api/auth.d.mts +4 -0
  117. package/dist/exports/cli/api/cache.d.mts +2 -2
  118. package/dist/exports/cli/api/event.mjs +126 -1
  119. package/dist/exports/cli/api/redis.mjs +3 -1
  120. package/dist/exports/cli/api/workflow.mjs +135 -1
  121. package/dist/exports/cli/api/workflows/extract-blob-metadata.mjs +132 -1
  122. package/dist/exports/cli/api/workflows/generate-image-variant.mjs +118 -1
  123. package/dist/exports/cli/api/workflows/generate-preview.mjs +160 -1
  124. package/dist/exports/cli/api/workflows/purge-attachment.mjs +34 -1
  125. package/dist/exports/cli/api/workflows/purge-audit-logs.mjs +47 -1
  126. package/dist/exports/cli/api/workflows/purge-unattached-blobs.mjs +46 -1
  127. package/dist/exports/cli/api/workflows/track-db-changes.mjs +110 -1
  128. package/dist/exports/cli/command.d.mts +2 -0
  129. package/dist/exports/cli/command.mjs +43 -1
  130. package/dist/exports/cli/constants.mjs +23 -1
  131. package/dist/exports/cli/index.mjs +3 -1
  132. package/dist/exports/devtools/index.js +4 -1
  133. package/dist/exports/tests/api/auth.d.mts +4 -0
  134. package/dist/exports/tests/api/cache.d.mts +2 -2
  135. package/dist/exports/tests/api/middleware/i18n.mjs +1 -1
  136. package/dist/exports/tests/api/middleware/youch-handler.mjs +1 -1
  137. package/dist/exports/tests/api/openapi.mjs +1 -1
  138. package/dist/exports/tests/api/server.mjs +1 -1
  139. package/dist/exports/tests/constants.mjs +1 -1
  140. package/dist/exports/vendors/date.js +1 -1
  141. package/dist/exports/vendors/toolkit.js +1 -1
  142. package/dist/exports/vendors/zod.js +1 -1
  143. package/dist/exports/vitest/globals.mjs +1 -1
  144. package/dist/exports/web/auth.js +75 -1
  145. package/dist/exports/web/i18n.js +45 -1
  146. package/dist/exports/web/index.js +8 -1
  147. package/package.json +19 -17
  148. package/dist/bin/auth-schema-Va0CYicu.mjs +0 -2
  149. package/dist/bin/event-8JibGFH_.mjs +0 -2
  150. package/dist/bin/extract-blob-metadata-DjPfHtQ2.mjs +0 -2
  151. package/dist/bin/generate-image-variant-D5VDFyWj.mjs +0 -2
  152. package/dist/bin/generate-preview-Dssw7w5U.mjs +0 -2
  153. package/dist/bin/purge-attachment-BBPzIxwt.mjs +0 -2
  154. package/dist/bin/purge-audit-logs-BeZy3IFM.mjs +0 -2
  155. package/dist/bin/track-db-changes-CFykw_YO.mjs +0 -2
  156. package/dist/bin/workflow-BNUZrj4F.mjs +0 -2
  157. package/dist/bin/youch-handler-BadUgHb0.mjs +0 -2
@@ -1 +1,373 @@
1
- import{sql as e}from"drizzle-orm";import{pgTable as t}from"drizzle-orm/pg-core";function n(){let n=t(`accounts`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),accessToken:t.text(`access_token`),accessTokenExpiresAt:t.timestamp(`access_token_expires_at`,{mode:`string`,withTimezone:!0}),accountId:t.text(`account_id`).notNull(),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),idToken:t.text(`id_token`),providerId:t.text(`provider_id`).notNull(),password:t.text(`password`),userId:t.text(`user_id`).notNull().references(()=>l.id,{onDelete:`cascade`}),refreshToken:t.text(`refresh_token`),refreshTokenExpiresAt:t.timestamp(`refresh_token_expires_at`,{mode:`string`,withTimezone:!0}),scope:t.text(`scope`),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),r=t(`api_keys`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),name:t.text(`name`),enabled:t.boolean(`enabled`).default(!0),expiresAt:t.timestamp(`expires_at`,{mode:`string`,withTimezone:!0}),key:t.text(`key`).notNull(),lastRefillAt:t.timestamp(`last_refill_at`,{mode:`string`,withTimezone:!0}),lastRequest:t.timestamp(`last_request`,{mode:`string`,withTimezone:!0}),lastUsedAt:t.timestamp(`last_used_at`,{mode:`string`,withTimezone:!0}),metadata:t.text(`metadata`),permissions:t.text(`permissions`),prefix:t.text(`prefix`),rateLimitEnabled:t.boolean(`rate_limit_enabled`).default(!0),rateLimitTimeWindow:t.integer(`rate_limit_time_window`).default(864e5),rateLimitMax:t.integer(`rate_limit_max`).default(10),refillInterval:t.integer(`refill_interval`),refillAmount:t.integer(`refill_amount`),requestCount:t.integer(`request_count`),remaining:t.integer(`remaining`),start:t.text(`start`),userId:t.text(`user_id`).notNull().references(()=>l.id,{onDelete:`cascade`}),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),i=t(`invitations`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),email:t.text(`email`).notNull(),expiresAt:t.timestamp(`expires_at`,{mode:`string`,withTimezone:!0}).notNull(),inviterId:t.text(`inviter_id`).notNull().references(()=>l.id,{onDelete:`cascade`}),organizationId:t.text(`organization_id`).notNull().references(()=>o.id,{onDelete:`cascade`}),role:t.text(`role`),status:t.text(`status`).default(`pending`).notNull(),teamId:t.text(`team_id`),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),a=t(`members`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),organizationId:t.text(`organization_id`).notNull().references(()=>o.id,{onDelete:`cascade`}),role:t.text(`role`).default(`member`).notNull(),userId:t.text(`user_id`).notNull().references(()=>l.id,{onDelete:`cascade`}),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),o=t(`organizations`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),name:t.text(`name`).notNull(),slug:t.text(`slug`).unique(),logo:t.text(`logo`),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),metadata:t.text(`metadata`)}),e=>[]),s=t(`sessions`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),activeOrganizationId:t.text(`active_organization_id`).references(()=>o.id,{onDelete:`set null`}),activeTeamId:t.text(`active_team_id`),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),expiresAt:t.timestamp(`expires_at`,{mode:`string`,withTimezone:!0}).notNull(),impersonatedBy:t.text(`impersonated_by`).references(()=>l.id,{onDelete:`set null`}),ipAddress:t.text(`ip_address`),token:t.text(`token`).notNull().unique(),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),userAgent:t.text(`user_agent`),userId:t.text(`user_id`).notNull().references(()=>l.id,{onDelete:`cascade`})}),e=>[]),c=t(`sso_providers`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),domain:t.text(`domain`).notNull(),issuer:t.text(`issuer`).notNull(),oidcConfig:t.text(`oidc_config`),organizationId:t.text(`organization_id`).references(()=>o.id,{onDelete:`cascade`}),providerId:t.text(`provider_id`).notNull().unique(),samlConfig:t.text(`saml_config`),userId:t.text(`user_id`).references(()=>l.id,{onDelete:`cascade`})}),e=>[]),l=t(`users`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),banExpires:t.timestamp(`ban_expires`,{mode:`string`,withTimezone:!0}),banReason:t.text(`ban_reason`),banned:t.boolean(`banned`).default(!1),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),displayUsername:t.text(`display_username`),email:t.text(`email`).notNull().unique(),emailVerified:t.boolean(`email_verified`).default(!1).notNull(),image:t.text(`image`),isAnonymous:t.boolean(`is_anonymous`),lastLoginMethod:t.text(`last_login_method`),name:t.text(`name`).notNull(),phoneNumber:t.text(`phone_number`).unique(),phoneNumberVerified:t.boolean(`phone_number_verified`),role:t.text(`role`),twoFactorEnabled:t.boolean(`two_factor_enabled`).default(!1),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),username:t.text(`username`).unique()}),e=>[]),u=t(`teams`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),name:t.text(`name`).notNull(),organizationId:t.text(`organization_id`).notNull().references(()=>o.id,{onDelete:`cascade`}),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),d=t(`team_members`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),teamId:t.text(`team_id`).notNull().references(()=>u.id,{onDelete:`cascade`}),userId:t.text(`user_id`).notNull().references(()=>l.id,{onDelete:`cascade`}),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),f=t(`two_factors`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),secret:t.text(`secret`).notNull(),backupCodes:t.text(`backup_codes`).notNull(),userId:t.text(`user_id`).notNull().references(()=>l.id,{onDelete:`cascade`})}),e=>[]),p=t(`verifications`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),expiresAt:t.timestamp(`expires_at`,{mode:`string`,withTimezone:!0}).notNull(),identifier:t.text(`identifier`).notNull(),updatedAt:t.timestamp(`updated_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull(),value:t.text(`value`).notNull()}),e=>[]);return{tables:{accounts:n,apiKeys:r,auditLogs:t(`audit_logs`,t=>({id:t.text(`id`).primaryKey().default(e`uuidv7()`),tableName:t.text(`table_name`),action:t.text(`action`).notNull(),customAction:t.text(`custom_action`),oldData:t.jsonb(`old_data`),newData:t.jsonb(`new_data`),metadata:t.jsonb(`metadata`),organizationId:t.text(`organization_id`).references(()=>o.id,{onDelete:`set null`}),userId:t.text(`user_id`).references(()=>l.id,{onDelete:`set null`}),sessionId:t.text(`session_id`).references(()=>s.id,{onDelete:`set null`}),requestId:t.text(`request_id`),createdAt:t.timestamp(`created_at`,{mode:`string`,withTimezone:!0}).default(e`NOW()`).notNull()}),e=>[]),invitations:i,members:a,organizations:o,sessions:s,ssoProviders:c,teams:u,teamMembers:d,twoFactors:f,users:l,verifications:p},relations:e=>({users:{sessions:e.many.sessions({from:e.users.id,to:e.sessions.userId}),accounts:e.many.accounts({from:e.users.id,to:e.accounts.userId}),apiKeys:e.many.apiKeys({from:e.users.id,to:e.apiKeys.userId}),memberships:e.many.members({from:e.users.id,to:e.members.userId}),invitations:e.many.invitations({from:e.users.id,to:e.invitations.inviterId}),ssoProvider:e.one.ssoProviders({from:e.users.id,to:e.ssoProviders.userId}),twoFactor:e.one.twoFactors({from:e.users.id,to:e.twoFactors.userId})},sessions:{user:e.one.users({from:e.sessions.userId,to:e.users.id})},accounts:{user:e.one.users({from:e.accounts.userId,to:e.users.id})},apiKeys:{user:e.one.users({from:e.apiKeys.userId,to:e.users.id})},organizations:{members:e.many.members({from:e.organizations.id,to:e.members.organizationId}),invitations:e.many.invitations({from:e.organizations.id,to:e.invitations.organizationId}),teams:e.many.teams({from:e.organizations.id,to:e.teams.organizationId})},members:{organization:e.one.organizations({from:e.members.organizationId,to:e.organizations.id}),user:e.one.users({from:e.members.userId,to:e.users.id})},invitations:{organization:e.one.organizations({from:e.invitations.organizationId,to:e.organizations.id}),inviter:e.one.users({from:e.invitations.inviterId,to:e.users.id})},teams:{organization:e.one.organizations({from:e.teams.organizationId,to:e.organizations.id})},ssoProviders:{user:e.one.users({from:e.ssoProviders.userId,to:e.users.id})},verifications:{},twoFactors:{user:e.one.users({from:e.twoFactors.userId,to:e.users.id})},auditLogs:{organization:e.one.organizations({from:e.auditLogs.organizationId,to:e.organizations.id}),user:e.one.users({from:e.auditLogs.userId,to:e.users.id}),session:e.one.sessions({from:e.auditLogs.sessionId,to:e.sessions.id})}})}}export{n as defineAuthSchema};
1
+ import { sql } from "drizzle-orm";
2
+ import { pgTable } from "drizzle-orm/pg-core";
3
+
4
+ //#region src/api/auth-schema.ts
5
+ /**
6
+ * Defines the authentication schema for the application.
7
+ *
8
+ * @returns An object containing the schema and relations for the authentication tables.
9
+ */
10
+ function defineAuthSchema() {
11
+ const accounts = pgTable("accounts", (t) => ({
12
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
13
+ accessToken: t.text("access_token"),
14
+ accessTokenExpiresAt: t.timestamp("access_token_expires_at", {
15
+ mode: "string",
16
+ withTimezone: true
17
+ }),
18
+ accountId: t.text("account_id").notNull(),
19
+ createdAt: t.timestamp("created_at", {
20
+ mode: "string",
21
+ withTimezone: true
22
+ }).default(sql`NOW()`).notNull(),
23
+ idToken: t.text("id_token"),
24
+ providerId: t.text("provider_id").notNull(),
25
+ password: t.text("password"),
26
+ userId: t.text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
27
+ refreshToken: t.text("refresh_token"),
28
+ refreshTokenExpiresAt: t.timestamp("refresh_token_expires_at", {
29
+ mode: "string",
30
+ withTimezone: true
31
+ }),
32
+ scope: t.text("scope"),
33
+ updatedAt: t.timestamp("updated_at", {
34
+ mode: "string",
35
+ withTimezone: true
36
+ }).default(sql`NOW()`).notNull()
37
+ }), (t) => []);
38
+ const apiKeys = pgTable("api_keys", (t) => ({
39
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
40
+ name: t.text("name"),
41
+ enabled: t.boolean("enabled").default(true),
42
+ expiresAt: t.timestamp("expires_at", {
43
+ mode: "string",
44
+ withTimezone: true
45
+ }),
46
+ key: t.text("key").notNull(),
47
+ lastRefillAt: t.timestamp("last_refill_at", {
48
+ mode: "string",
49
+ withTimezone: true
50
+ }),
51
+ lastRequest: t.timestamp("last_request", {
52
+ mode: "string",
53
+ withTimezone: true
54
+ }),
55
+ lastUsedAt: t.timestamp("last_used_at", {
56
+ mode: "string",
57
+ withTimezone: true
58
+ }),
59
+ metadata: t.text("metadata"),
60
+ permissions: t.text("permissions"),
61
+ prefix: t.text("prefix"),
62
+ rateLimitEnabled: t.boolean("rate_limit_enabled").default(true),
63
+ rateLimitTimeWindow: t.integer("rate_limit_time_window").default(864e5),
64
+ rateLimitMax: t.integer("rate_limit_max").default(10),
65
+ refillInterval: t.integer("refill_interval"),
66
+ refillAmount: t.integer("refill_amount"),
67
+ requestCount: t.integer("request_count"),
68
+ remaining: t.integer("remaining"),
69
+ start: t.text("start"),
70
+ userId: t.text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
71
+ createdAt: t.timestamp("created_at", {
72
+ mode: "string",
73
+ withTimezone: true
74
+ }).default(sql`NOW()`).notNull(),
75
+ updatedAt: t.timestamp("updated_at", {
76
+ mode: "string",
77
+ withTimezone: true
78
+ }).default(sql`NOW()`).notNull()
79
+ }), (t) => []);
80
+ const invitations = pgTable("invitations", (t) => ({
81
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
82
+ email: t.text("email").notNull(),
83
+ expiresAt: t.timestamp("expires_at", {
84
+ mode: "string",
85
+ withTimezone: true
86
+ }).notNull(),
87
+ inviterId: t.text("inviter_id").notNull().references(() => users.id, { onDelete: "cascade" }),
88
+ organizationId: t.text("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
89
+ role: t.text("role"),
90
+ status: t.text("status").default("pending").notNull(),
91
+ teamId: t.text("team_id"),
92
+ createdAt: t.timestamp("created_at", {
93
+ mode: "string",
94
+ withTimezone: true
95
+ }).default(sql`NOW()`).notNull(),
96
+ updatedAt: t.timestamp("updated_at", {
97
+ mode: "string",
98
+ withTimezone: true
99
+ }).default(sql`NOW()`).notNull()
100
+ }), (t) => []);
101
+ const members = pgTable("members", (t) => ({
102
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
103
+ organizationId: t.text("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
104
+ role: t.text("role").default("member").notNull(),
105
+ userId: t.text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
106
+ createdAt: t.timestamp("created_at", {
107
+ mode: "string",
108
+ withTimezone: true
109
+ }).default(sql`NOW()`).notNull()
110
+ }), (t) => []);
111
+ const organizations = pgTable("organizations", (t) => ({
112
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
113
+ name: t.text("name").notNull(),
114
+ slug: t.text("slug").unique(),
115
+ logo: t.text("logo"),
116
+ createdAt: t.timestamp("created_at", {
117
+ mode: "string",
118
+ withTimezone: true
119
+ }).default(sql`NOW()`).notNull(),
120
+ updatedAt: t.timestamp("updated_at", {
121
+ mode: "string",
122
+ withTimezone: true
123
+ }).default(sql`NOW()`).notNull(),
124
+ metadata: t.text("metadata")
125
+ }), (t) => []);
126
+ const sessions = pgTable("sessions", (t) => ({
127
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
128
+ activeOrganizationId: t.text("active_organization_id").references(() => organizations.id, { onDelete: "set null" }),
129
+ activeTeamId: t.text("active_team_id"),
130
+ createdAt: t.timestamp("created_at", {
131
+ mode: "string",
132
+ withTimezone: true
133
+ }).default(sql`NOW()`).notNull(),
134
+ expiresAt: t.timestamp("expires_at", {
135
+ mode: "string",
136
+ withTimezone: true
137
+ }).notNull(),
138
+ impersonatedBy: t.text("impersonated_by").references(() => users.id, { onDelete: "set null" }),
139
+ ipAddress: t.text("ip_address"),
140
+ token: t.text("token").notNull().unique(),
141
+ updatedAt: t.timestamp("updated_at", {
142
+ mode: "string",
143
+ withTimezone: true
144
+ }).default(sql`NOW()`).notNull(),
145
+ userAgent: t.text("user_agent"),
146
+ userId: t.text("user_id").notNull().references(() => users.id, { onDelete: "cascade" })
147
+ }), (t) => []);
148
+ const ssoProviders = pgTable("sso_providers", (t) => ({
149
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
150
+ domain: t.text("domain").notNull(),
151
+ issuer: t.text("issuer").notNull(),
152
+ oidcConfig: t.text("oidc_config"),
153
+ organizationId: t.text("organization_id").references(() => organizations.id, { onDelete: "cascade" }),
154
+ providerId: t.text("provider_id").notNull().unique(),
155
+ samlConfig: t.text("saml_config"),
156
+ userId: t.text("user_id").references(() => users.id, { onDelete: "cascade" })
157
+ }), (t) => []);
158
+ const users = pgTable("users", (t) => ({
159
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
160
+ banExpires: t.timestamp("ban_expires", {
161
+ mode: "string",
162
+ withTimezone: true
163
+ }),
164
+ banReason: t.text("ban_reason"),
165
+ banned: t.boolean("banned").default(false),
166
+ createdAt: t.timestamp("created_at", {
167
+ mode: "string",
168
+ withTimezone: true
169
+ }).default(sql`NOW()`).notNull(),
170
+ displayUsername: t.text("display_username"),
171
+ email: t.text("email").notNull().unique(),
172
+ emailVerified: t.boolean("email_verified").default(false).notNull(),
173
+ image: t.text("image"),
174
+ isAnonymous: t.boolean("is_anonymous"),
175
+ lastLoginMethod: t.text("last_login_method"),
176
+ name: t.text("name").notNull(),
177
+ phoneNumber: t.text("phone_number").unique(),
178
+ phoneNumberVerified: t.boolean("phone_number_verified"),
179
+ role: t.text("role"),
180
+ twoFactorEnabled: t.boolean("two_factor_enabled").default(false),
181
+ updatedAt: t.timestamp("updated_at", {
182
+ mode: "string",
183
+ withTimezone: true
184
+ }).default(sql`NOW()`).notNull(),
185
+ username: t.text("username").unique()
186
+ }), (t) => []);
187
+ const teams = pgTable("teams", (t) => ({
188
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
189
+ name: t.text("name").notNull(),
190
+ organizationId: t.text("organization_id").notNull().references(() => organizations.id, { onDelete: "cascade" }),
191
+ createdAt: t.timestamp("created_at", {
192
+ mode: "string",
193
+ withTimezone: true
194
+ }).default(sql`NOW()`).notNull(),
195
+ updatedAt: t.timestamp("updated_at", {
196
+ mode: "string",
197
+ withTimezone: true
198
+ }).default(sql`NOW()`).notNull()
199
+ }), (t) => []);
200
+ const teamMembers = pgTable("team_members", (t) => ({
201
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
202
+ teamId: t.text("team_id").notNull().references(() => teams.id, { onDelete: "cascade" }),
203
+ userId: t.text("user_id").notNull().references(() => users.id, { onDelete: "cascade" }),
204
+ createdAt: t.timestamp("created_at", {
205
+ mode: "string",
206
+ withTimezone: true
207
+ }).default(sql`NOW()`).notNull()
208
+ }), (t) => []);
209
+ const twoFactors = pgTable("two_factors", (t) => ({
210
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
211
+ secret: t.text("secret").notNull(),
212
+ backupCodes: t.text("backup_codes").notNull(),
213
+ userId: t.text("user_id").notNull().references(() => users.id, { onDelete: "cascade" })
214
+ }), (t) => []);
215
+ const verifications = pgTable("verifications", (t) => ({
216
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
217
+ createdAt: t.timestamp("created_at", {
218
+ mode: "string",
219
+ withTimezone: true
220
+ }).default(sql`NOW()`).notNull(),
221
+ expiresAt: t.timestamp("expires_at", {
222
+ mode: "string",
223
+ withTimezone: true
224
+ }).notNull(),
225
+ identifier: t.text("identifier").notNull(),
226
+ updatedAt: t.timestamp("updated_at", {
227
+ mode: "string",
228
+ withTimezone: true
229
+ }).default(sql`NOW()`).notNull(),
230
+ value: t.text("value").notNull()
231
+ }), (t) => []);
232
+ return {
233
+ tables: {
234
+ accounts,
235
+ apiKeys,
236
+ auditLogs: pgTable("audit_logs", (t) => ({
237
+ id: t.text("id").primaryKey().default(sql`uuidv7()`),
238
+ tableName: t.text("table_name"),
239
+ action: t.text("action").notNull(),
240
+ customAction: t.text("custom_action"),
241
+ oldData: t.jsonb("old_data"),
242
+ newData: t.jsonb("new_data"),
243
+ metadata: t.jsonb("metadata"),
244
+ organizationId: t.text("organization_id").references(() => organizations.id, { onDelete: "set null" }),
245
+ userId: t.text("user_id").references(() => users.id, { onDelete: "set null" }),
246
+ sessionId: t.text("session_id").references(() => sessions.id, { onDelete: "set null" }),
247
+ requestId: t.text("request_id"),
248
+ createdAt: t.timestamp("created_at", {
249
+ mode: "string",
250
+ withTimezone: true
251
+ }).default(sql`NOW()`).notNull()
252
+ }), (t) => []),
253
+ invitations,
254
+ members,
255
+ organizations,
256
+ sessions,
257
+ ssoProviders,
258
+ teams,
259
+ teamMembers,
260
+ twoFactors,
261
+ users,
262
+ verifications
263
+ },
264
+ relations: (r) => ({
265
+ users: {
266
+ sessions: r.many.sessions({
267
+ from: r.users.id,
268
+ to: r.sessions.userId
269
+ }),
270
+ accounts: r.many.accounts({
271
+ from: r.users.id,
272
+ to: r.accounts.userId
273
+ }),
274
+ apiKeys: r.many.apiKeys({
275
+ from: r.users.id,
276
+ to: r.apiKeys.userId
277
+ }),
278
+ memberships: r.many.members({
279
+ from: r.users.id,
280
+ to: r.members.userId
281
+ }),
282
+ invitations: r.many.invitations({
283
+ from: r.users.id,
284
+ to: r.invitations.inviterId
285
+ }),
286
+ ssoProvider: r.one.ssoProviders({
287
+ from: r.users.id,
288
+ to: r.ssoProviders.userId
289
+ }),
290
+ twoFactor: r.one.twoFactors({
291
+ from: r.users.id,
292
+ to: r.twoFactors.userId
293
+ })
294
+ },
295
+ sessions: { user: r.one.users({
296
+ from: r.sessions.userId,
297
+ to: r.users.id
298
+ }) },
299
+ accounts: { user: r.one.users({
300
+ from: r.accounts.userId,
301
+ to: r.users.id
302
+ }) },
303
+ apiKeys: { user: r.one.users({
304
+ from: r.apiKeys.userId,
305
+ to: r.users.id
306
+ }) },
307
+ organizations: {
308
+ members: r.many.members({
309
+ from: r.organizations.id,
310
+ to: r.members.organizationId
311
+ }),
312
+ invitations: r.many.invitations({
313
+ from: r.organizations.id,
314
+ to: r.invitations.organizationId
315
+ }),
316
+ teams: r.many.teams({
317
+ from: r.organizations.id,
318
+ to: r.teams.organizationId
319
+ })
320
+ },
321
+ members: {
322
+ organization: r.one.organizations({
323
+ from: r.members.organizationId,
324
+ to: r.organizations.id
325
+ }),
326
+ user: r.one.users({
327
+ from: r.members.userId,
328
+ to: r.users.id
329
+ })
330
+ },
331
+ invitations: {
332
+ organization: r.one.organizations({
333
+ from: r.invitations.organizationId,
334
+ to: r.organizations.id
335
+ }),
336
+ inviter: r.one.users({
337
+ from: r.invitations.inviterId,
338
+ to: r.users.id
339
+ })
340
+ },
341
+ teams: { organization: r.one.organizations({
342
+ from: r.teams.organizationId,
343
+ to: r.organizations.id
344
+ }) },
345
+ ssoProviders: { user: r.one.users({
346
+ from: r.ssoProviders.userId,
347
+ to: r.users.id
348
+ }) },
349
+ verifications: {},
350
+ twoFactors: { user: r.one.users({
351
+ from: r.twoFactors.userId,
352
+ to: r.users.id
353
+ }) },
354
+ auditLogs: {
355
+ organization: r.one.organizations({
356
+ from: r.auditLogs.organizationId,
357
+ to: r.organizations.id
358
+ }),
359
+ user: r.one.users({
360
+ from: r.auditLogs.userId,
361
+ to: r.users.id
362
+ }),
363
+ session: r.one.sessions({
364
+ from: r.auditLogs.sessionId,
365
+ to: r.sessions.id
366
+ })
367
+ }
368
+ })
369
+ };
370
+ }
371
+
372
+ //#endregion
373
+ export { defineAuthSchema };
@@ -347,6 +347,10 @@ type DefineAuthOptions<T extends AuthConfig, TDb = unknown> = {
347
347
  * Hooks for email sending and OTP delivery.
348
348
  */
349
349
  hooks: RequiredHooks<T>;
350
+ /**
351
+ * Secret key for signing tokens and cookies.
352
+ */
353
+ secret: string;
350
354
  /**
351
355
  * Session configuration.
352
356
  */
@@ -1,5 +1,5 @@
1
1
  import { Logger } from "./logger.mjs";
2
- import * as keyv0 from "keyv";
2
+ import * as _keyv_redis0 from "@keyv/redis";
3
3
  import { KeyvRedisOptions } from "@keyv/redis";
4
4
 
5
5
  //#region src/api/cache.d.ts
@@ -39,6 +39,6 @@ declare function defineCache({
39
39
  url,
40
40
  logger,
41
41
  options
42
- }: DefineCacheOptions): keyv0.Keyv<any>;
42
+ }: DefineCacheOptions): _keyv_redis0.Keyv<any>;
43
43
  //#endregion
44
44
  export { Cache };
@@ -1 +1,126 @@
1
- import"../constants.mjs";import"./redis.mjs";import{join as e}from"node:path";import{z as t}from"zod";import"es-toolkit";function n(e){let t=null,n=null;return{inputSchema:e.input,get name(){return n},register(e,r){t=e,n=r},async emit(r){if(!t||!n)throw Error(`Event not registered. Ensure the worker is started before emitting events.`);let i=e.input.parse(r),a={container:t,input:i};await e.run(a),t.eventBus.publish(n,i).catch(e=>{t.logger.error({err:e,event:n},`Redis publish failed`)})},async subscribe(r){if(!t||!n)throw Error(`Event not registered. Ensure the worker is started before subscribing.`);return t.eventBus.subscribe(n,async i=>{let a=e.input.parse(i),o={container:t,input:a};try{await r(o)}catch(e){t.logger.error({err:e,event:n},`Event subscription handler error`)}})}}}const r=n({input:t.object({action:t.enum([`INSERT`,`UPDATE`,`DELETE`]),newData:t.record(t.string(),t.unknown()).nullable(),oldData:t.record(t.string(),t.unknown()).nullable(),organizationId:t.string().nullable(),tableName:t.string(),timestamp:t.string(),userId:t.string().nullable()}),async run(){}});export{r as dbChangesEvent};
1
+ import "../constants.mjs";
2
+ import "./redis.mjs";
3
+ import { join } from "node:path";
4
+ import { z } from "zod";
5
+ import "es-toolkit";
6
+
7
+ //#region src/api/event.ts
8
+ /**
9
+ * Defines a type-safe event with in-memory and Redis pub/sub support.
10
+ *
11
+ * Algorithm:
12
+ * 1. Define event with input schema and in-memory run handler
13
+ * 2. On emit(): validate input, run in-memory handler, publish to Redis (fire-and-forget)
14
+ * 3. .subscribe() creates Redis subscription for tRPC/SSE/WebSocket handlers
15
+ *
16
+ * @example
17
+ * ```typescript
18
+ * // api/events/order-status.ts
19
+ * export default defineEvent({
20
+ * input: z.object({
21
+ * orderId: z.string(),
22
+ * status: z.enum(["pending", "shipped", "delivered"]),
23
+ * }),
24
+ * async run(ctx) {
25
+ * ctx.container.logger.info(`Order ${ctx.input.orderId} is ${ctx.input.status}`);
26
+ * },
27
+ * });
28
+ *
29
+ * // Emit from anywhere
30
+ * await orderStatus.emit({ orderId: "123", status: "shipped" });
31
+ *
32
+ * // Subscribe (e.g., in tRPC router)
33
+ * const unsubscribe = await orderStatus.subscribe(async (ctx) => {
34
+ * // Push to client via SSE/WebSocket
35
+ * });
36
+ * // Cleanup when client disconnects
37
+ * unsubscribe();
38
+ * ```
39
+ */
40
+ function defineEvent(options) {
41
+ let container = null;
42
+ let eventName = null;
43
+ return {
44
+ inputSchema: options.input,
45
+ get name() {
46
+ return eventName;
47
+ },
48
+ register(c, name) {
49
+ container = c;
50
+ eventName = name;
51
+ },
52
+ async emit(input) {
53
+ if (!container || !eventName) throw new Error("Event not registered. Ensure the worker is started before emitting events.");
54
+ const validated = options.input.parse(input);
55
+ const ctx = {
56
+ container,
57
+ input: validated
58
+ };
59
+ await options.run(ctx);
60
+ container.eventBus.publish(eventName, validated).catch((err) => {
61
+ container.logger.error({
62
+ err,
63
+ event: eventName
64
+ }, "Redis publish failed");
65
+ });
66
+ },
67
+ async subscribe(handler) {
68
+ if (!container || !eventName) throw new Error("Event not registered. Ensure the worker is started before subscribing.");
69
+ return container.eventBus.subscribe(eventName, async (message) => {
70
+ const validated = options.input.parse(message);
71
+ const ctx = {
72
+ container,
73
+ input: validated
74
+ };
75
+ try {
76
+ await handler(ctx);
77
+ } catch (err) {
78
+ container.logger.error({
79
+ err,
80
+ event: eventName
81
+ }, "Event subscription handler error");
82
+ }
83
+ });
84
+ }
85
+ };
86
+ }
87
+ /**
88
+ * Input schema for dbChangesEvent.
89
+ */
90
+ const dbChangeInputSchema = z.object({
91
+ action: z.enum([
92
+ "INSERT",
93
+ "UPDATE",
94
+ "DELETE"
95
+ ]),
96
+ newData: z.record(z.string(), z.unknown()).nullable(),
97
+ oldData: z.record(z.string(), z.unknown()).nullable(),
98
+ organizationId: z.string().nullable(),
99
+ tableName: z.string(),
100
+ timestamp: z.string(),
101
+ userId: z.string().nullable()
102
+ });
103
+ /**
104
+ * Built-in event for database changes.
105
+ * Emitted by trackDbChanges workflow.
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * // Subscribe to DB changes (e.g., in tRPC subscription)
110
+ * import { dbChangesEvent } from "appos/api";
111
+ *
112
+ * const unsubscribe = await dbChangesEvent.subscribe(async (ctx) => {
113
+ * wsServer.publish("db-changes", JSON.stringify(ctx.input));
114
+ * });
115
+ *
116
+ * // Cleanup when done
117
+ * unsubscribe();
118
+ * ```
119
+ */
120
+ const dbChangesEvent = defineEvent({
121
+ input: dbChangeInputSchema,
122
+ async run() {}
123
+ });
124
+
125
+ //#endregion
126
+ export { dbChangesEvent };
@@ -1 +1,3 @@
1
- import"redis";export{};
1
+ import "redis";
2
+
3
+ export { };
@@ -1 +1,135 @@
1
- import"../constants.mjs";import{join as e}from"node:path";import"es-toolkit";function t(e){let t=null,n=null,r=null,i=null,a=async i=>{if(!t||!r)throw Error(`Workflow "${n}" not registered`);let a=r,o=a.workflowID;if(!o)throw Error(`DBOS.workflowID is not available in this context`);let s={container:t,workflowId:o,input:i,step:(e,t)=>a.runStep(t,{name:e})};return e.run(s)};return{inputSchema:e.input,get name(){return n},register(o,s,c){t=o,n=s,r=c,i=c.registerWorkflow(a,{name:s,...e.config})},async start(t){if(!i||!n||!r)throw Error(`Workflow not registered. Ensure the worker is started before triggering workflows.`);let a=e.input.parse(t),o=await r.startWorkflow(i)(a);return{workflowId:o.workflowID,getStatus:()=>o.getStatus(),getResult:()=>o.getResult()}}}}function n(e){let t=null,n=null,r=null,i=async(i,a)=>{if(!t||!r)throw Error(`Workflow "${n}" not registered`);let o=r,s=o.workflowID;if(!s)throw Error(`DBOS.workflowID is not available in this context`);let c={container:t,workflowId:s,scheduledTime:i,step:(e,t)=>o.runStep(t,{name:e})};return e.run(c)};return{crontab:e.crontab,get name(){return n},register(a,o,s){t=a,n=o,r=s,s.registerScheduled(s.registerWorkflow(i,{name:o}),{crontab:e.crontab})}}}export{n as defineScheduledWorkflow,t as defineWorkflow};
1
+ import "../constants.mjs";
2
+ import { join } from "node:path";
3
+ import "es-toolkit";
4
+
5
+ //#region src/api/workflow.ts
6
+ /**
7
+ * Defines a durable workflow that can be triggered with type-safe input.
8
+ *
9
+ * Workflows are:
10
+ * - Durable: Automatically resume after crashes or restarts
11
+ * - Type-safe: Input and output types are inferred from the schema
12
+ * - Container-aware: Access to db, mailer, logger via ctx.container
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * // api/workflows/send-welcome-email.ts
17
+ * export default defineWorkflow({
18
+ * input: z.object({
19
+ * userId: z.string(),
20
+ * email: z.string().email(),
21
+ * }),
22
+ * async run(ctx) {
23
+ * const user = await ctx.container.db.primary.query.users.findFirst({
24
+ * where: eq(users.id, ctx.input.userId),
25
+ * });
26
+ *
27
+ * await ctx.container.mailer.send({
28
+ * to: ctx.input.email,
29
+ * subject: "Welcome!",
30
+ * });
31
+ *
32
+ * return { sent: true };
33
+ * },
34
+ * });
35
+ *
36
+ * // Triggering from a route:
37
+ * import sendWelcomeEmail from "#api/workflows/send-welcome-email.ts";
38
+ * const handle = await sendWelcomeEmail.start({ userId: "123", email: "..." });
39
+ * ```
40
+ */
41
+ function defineWorkflow(options) {
42
+ let container = null;
43
+ let workflowName = null;
44
+ let dbosInstance = null;
45
+ let registeredFn = null;
46
+ const workflowFn = async (input) => {
47
+ if (!container || !dbosInstance) throw new Error(`Workflow "${workflowName}" not registered`);
48
+ const dbos = dbosInstance;
49
+ const workflowId = dbos.workflowID;
50
+ if (!workflowId) throw new Error("DBOS.workflowID is not available in this context");
51
+ const ctx = {
52
+ container,
53
+ workflowId,
54
+ input,
55
+ step: (name, fn) => dbos.runStep(fn, { name })
56
+ };
57
+ return options.run(ctx);
58
+ };
59
+ return {
60
+ inputSchema: options.input,
61
+ get name() {
62
+ return workflowName;
63
+ },
64
+ register(c, name, dbos) {
65
+ container = c;
66
+ workflowName = name;
67
+ dbosInstance = dbos;
68
+ registeredFn = dbos.registerWorkflow(workflowFn, {
69
+ name,
70
+ ...options.config
71
+ });
72
+ },
73
+ async start(input) {
74
+ if (!registeredFn || !workflowName || !dbosInstance) throw new Error("Workflow not registered. Ensure the worker is started before triggering workflows.");
75
+ const validated = options.input.parse(input);
76
+ const handle = await dbosInstance.startWorkflow(registeredFn)(validated);
77
+ return {
78
+ workflowId: handle.workflowID,
79
+ getStatus: () => handle.getStatus(),
80
+ getResult: () => handle.getResult()
81
+ };
82
+ }
83
+ };
84
+ }
85
+ /**
86
+ * Defines a scheduled workflow that runs on a cron schedule.
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * // api/workflows/daily-report.ts
91
+ * export default defineScheduledWorkflow({
92
+ * crontab: "0 9 * * *", // 9am daily
93
+ * async run(ctx) {
94
+ * const stats = await ctx.container.db.primary.query.stats.findMany();
95
+ * await ctx.container.mailer.send({
96
+ * to: "team@company.com",
97
+ * subject: `Daily Report - ${ctx.scheduledTime.toDateString()}`,
98
+ * });
99
+ * },
100
+ * });
101
+ * ```
102
+ */
103
+ function defineScheduledWorkflow(options) {
104
+ let container = null;
105
+ let workflowName = null;
106
+ let dbosInstance = null;
107
+ const workflowFn = async (scheduledTime, _startTime) => {
108
+ if (!container || !dbosInstance) throw new Error(`Workflow "${workflowName}" not registered`);
109
+ const dbos = dbosInstance;
110
+ const workflowId = dbos.workflowID;
111
+ if (!workflowId) throw new Error("DBOS.workflowID is not available in this context");
112
+ const ctx = {
113
+ container,
114
+ workflowId,
115
+ scheduledTime,
116
+ step: (name, fn) => dbos.runStep(fn, { name })
117
+ };
118
+ return options.run(ctx);
119
+ };
120
+ return {
121
+ crontab: options.crontab,
122
+ get name() {
123
+ return workflowName;
124
+ },
125
+ register(c, name, dbos) {
126
+ container = c;
127
+ workflowName = name;
128
+ dbosInstance = dbos;
129
+ dbos.registerScheduled(dbos.registerWorkflow(workflowFn, { name }), { crontab: options.crontab });
130
+ }
131
+ };
132
+ }
133
+
134
+ //#endregion
135
+ export { defineScheduledWorkflow, defineWorkflow };