appos 0.2.1 → 0.2.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 (232) hide show
  1. package/dist/bin/auth-schema-7KeUwlcd.mjs +2 -0
  2. package/dist/bin/concurrently.mjs +2 -0
  3. package/dist/bin/event-v2sCJkNd.mjs +2 -0
  4. package/dist/bin/extract-blob-metadata-TqNd9w-6.mjs +2 -0
  5. package/dist/bin/generate-image-variant-D8H9FxgD.mjs +2 -0
  6. package/dist/bin/generate-preview-5jLZLX6I.mjs +2 -0
  7. package/dist/bin/main.mjs +362 -0
  8. package/dist/bin/purge-attachment-CMlJMNOk.mjs +2 -0
  9. package/dist/bin/purge-audit-logs-hd6q6vnR.mjs +2 -0
  10. package/dist/bin/purge-unattached-blobs-BYv5b9R9.mjs +2 -0
  11. package/dist/bin/track-db-changes-q0Vl7Htm.mjs +2 -0
  12. package/dist/bin/vite.mjs +2 -0
  13. package/dist/bin/vitest.mjs +2 -0
  14. package/dist/bin/workflow-BagSlsMp.mjs +2 -0
  15. package/dist/bin/youch-handler-Jj6i1XIT.mjs +2 -0
  16. package/dist/exports/api/_virtual/rolldown_runtime.mjs +1 -0
  17. package/dist/exports/api/app-context.d.mts +115 -0
  18. package/dist/exports/api/app-context.mjs +1 -0
  19. package/dist/exports/api/auth-schema.d.mts +4248 -0
  20. package/dist/exports/api/auth-schema.mjs +1 -0
  21. package/dist/exports/api/auth.d.mts +398 -0
  22. package/dist/exports/api/auth.mjs +1 -0
  23. package/dist/exports/api/cache.d.mts +44 -0
  24. package/dist/exports/api/cache.mjs +1 -0
  25. package/dist/exports/api/config.d.mts +28 -0
  26. package/dist/exports/api/config.mjs +1 -0
  27. package/dist/exports/api/container.d.mts +210 -0
  28. package/dist/exports/api/container.mjs +1 -0
  29. package/dist/exports/api/database.d.mts +99 -0
  30. package/dist/exports/api/database.mjs +1 -0
  31. package/dist/exports/api/event.d.mts +235 -0
  32. package/dist/exports/api/event.mjs +1 -0
  33. package/dist/exports/api/i18n.d.mts +34 -0
  34. package/dist/exports/api/i18n.mjs +1 -0
  35. package/dist/exports/api/index.d.mts +21 -0
  36. package/dist/exports/api/index.mjs +1 -0
  37. package/dist/exports/api/logger.d.mts +21 -0
  38. package/dist/exports/api/logger.mjs +1 -0
  39. package/dist/exports/api/mailer.d.mts +70 -0
  40. package/dist/exports/api/mailer.mjs +1 -0
  41. package/dist/exports/api/middleware/request-logger.d.mts +24 -0
  42. package/dist/exports/api/middleware.d.mts +39 -0
  43. package/dist/exports/api/middleware.mjs +1 -0
  44. package/dist/exports/api/node_modules/.bun/change-case@5.4.4/node_modules/change-case/dist/index.mjs +1 -0
  45. package/dist/exports/api/openapi.d.mts +271 -0
  46. package/dist/exports/api/openapi.mjs +1 -0
  47. package/dist/exports/api/orm.d.mts +13 -0
  48. package/dist/exports/api/orm.mjs +1 -0
  49. package/dist/exports/api/otel.d.mts +40 -0
  50. package/dist/exports/api/otel.mjs +1 -0
  51. package/dist/exports/api/packages/appos/src/constants.mjs +1 -0
  52. package/dist/exports/api/packages/appos/src/instrumentation.d.mts +7 -0
  53. package/dist/exports/api/packages/appos/src/instrumentation.mjs +1 -0
  54. package/dist/exports/api/packages/appos/src/web/auth.mjs +1 -0
  55. package/dist/exports/api/redis.d.mts +34 -0
  56. package/dist/exports/api/redis.mjs +1 -0
  57. package/dist/exports/api/storage-schema.d.mts +707 -0
  58. package/dist/exports/api/storage-schema.mjs +1 -0
  59. package/dist/exports/api/storage.d.mts +506 -0
  60. package/dist/exports/api/storage.mjs +1 -0
  61. package/dist/exports/api/workflow.d.mts +250 -0
  62. package/dist/exports/api/workflow.mjs +1 -0
  63. package/dist/exports/api/workflows/_virtual/rolldown_runtime.mjs +1 -0
  64. package/dist/exports/api/workflows/auth-schema.mjs +1 -0
  65. package/dist/exports/api/workflows/auth.d.mts +375 -0
  66. package/dist/exports/api/workflows/cache.d.mts +44 -0
  67. package/dist/exports/api/workflows/config.d.mts +18 -0
  68. package/dist/exports/api/workflows/container.d.mts +167 -0
  69. package/dist/exports/api/workflows/database.d.mts +46 -0
  70. package/dist/exports/api/workflows/event.d.mts +68 -0
  71. package/dist/exports/api/workflows/event.mjs +1 -0
  72. package/dist/exports/api/workflows/extract-blob-metadata.mjs +1 -0
  73. package/dist/exports/api/workflows/generate-image-variant.d.mts +63 -0
  74. package/dist/exports/api/workflows/generate-image-variant.mjs +1 -0
  75. package/dist/exports/api/workflows/generate-preview.mjs +1 -0
  76. package/dist/exports/api/workflows/index.d.mts +2 -0
  77. package/dist/exports/api/workflows/index.mjs +1 -0
  78. package/dist/exports/api/workflows/logger.d.mts +21 -0
  79. package/dist/exports/api/workflows/mailer.d.mts +70 -0
  80. package/dist/exports/api/workflows/orm.d.mts +13 -0
  81. package/dist/exports/api/workflows/purge-attachment.mjs +1 -0
  82. package/dist/exports/api/workflows/purge-audit-logs.mjs +1 -0
  83. package/dist/exports/api/workflows/purge-unattached-blobs.mjs +1 -0
  84. package/dist/exports/api/workflows/redis.mjs +1 -0
  85. package/dist/exports/api/workflows/storage-schema.d.mts +699 -0
  86. package/dist/exports/api/workflows/storage.d.mts +396 -0
  87. package/dist/exports/api/workflows/track-db-changes.d.mts +72 -0
  88. package/dist/exports/api/workflows/track-db-changes.mjs +1 -0
  89. package/dist/exports/api/workflows/workflow.d.mts +24 -0
  90. package/dist/exports/api/workflows/workflow.mjs +1 -0
  91. package/dist/exports/cli/_virtual/rolldown_runtime.mjs +1 -0
  92. package/dist/exports/cli/api/auth-schema.mjs +1 -0
  93. package/dist/exports/cli/api/auth.d.mts +375 -0
  94. package/dist/exports/cli/api/cache.d.mts +44 -0
  95. package/dist/exports/cli/api/config.d.mts +18 -0
  96. package/dist/exports/cli/api/container.d.mts +167 -0
  97. package/dist/exports/cli/api/database.d.mts +46 -0
  98. package/dist/exports/cli/api/event.d.mts +68 -0
  99. package/dist/exports/cli/api/event.mjs +1 -0
  100. package/dist/exports/cli/api/logger.d.mts +21 -0
  101. package/dist/exports/cli/api/mailer.d.mts +70 -0
  102. package/dist/exports/cli/api/orm.d.mts +13 -0
  103. package/dist/exports/cli/api/redis.mjs +1 -0
  104. package/dist/exports/cli/api/storage-schema.d.mts +699 -0
  105. package/dist/exports/cli/api/storage.d.mts +396 -0
  106. package/dist/exports/cli/api/workflow.d.mts +2 -0
  107. package/dist/exports/cli/api/workflow.mjs +1 -0
  108. package/dist/exports/cli/api/workflows/extract-blob-metadata.mjs +1 -0
  109. package/dist/exports/cli/api/workflows/generate-image-variant.d.mts +63 -0
  110. package/dist/exports/cli/api/workflows/generate-image-variant.mjs +1 -0
  111. package/dist/exports/cli/api/workflows/generate-preview.mjs +1 -0
  112. package/dist/exports/cli/api/workflows/purge-attachment.mjs +1 -0
  113. package/dist/exports/cli/api/workflows/purge-audit-logs.mjs +1 -0
  114. package/dist/exports/cli/api/workflows/purge-unattached-blobs.mjs +1 -0
  115. package/dist/exports/cli/api/workflows/track-db-changes.mjs +1 -0
  116. package/dist/exports/cli/command.d.mts +54 -0
  117. package/dist/exports/cli/command.mjs +1 -0
  118. package/dist/exports/cli/context.d.mts +170 -0
  119. package/dist/exports/cli/index.d.mts +3 -0
  120. package/dist/exports/cli/index.mjs +1 -0
  121. package/dist/exports/devtools/index.d.ts +3 -0
  122. package/dist/exports/devtools/index.js +1 -0
  123. package/dist/exports/instrumentation.d.mts +1 -0
  124. package/dist/exports/instrumentation.mjs +1 -0
  125. package/dist/exports/tests/_virtual/rolldown_runtime.mjs +1 -0
  126. package/dist/exports/tests/api.d.mts +86 -0
  127. package/dist/exports/tests/api.mjs +1 -0
  128. package/dist/exports/tests/mock.d.mts +1 -0
  129. package/dist/exports/tests/mock.mjs +1 -0
  130. package/dist/exports/tests/node_modules/.bun/change-case@5.4.4/node_modules/change-case/dist/index.mjs +1 -0
  131. package/dist/exports/tests/node_modules/.bun/rate-limit-redis@4.3.1_f1fa5524233c9c60/node_modules/rate-limit-redis/dist/index.mjs +25 -0
  132. package/dist/exports/tests/packages/appos/src/api/app-context.d.mts +115 -0
  133. package/dist/exports/tests/packages/appos/src/api/auth-schema.d.mts +4248 -0
  134. package/dist/exports/tests/packages/appos/src/api/auth-schema.mjs +1 -0
  135. package/dist/exports/tests/packages/appos/src/api/auth.d.mts +398 -0
  136. package/dist/exports/tests/packages/appos/src/api/cache.d.mts +44 -0
  137. package/dist/exports/tests/packages/appos/src/api/config.d.mts +28 -0
  138. package/dist/exports/tests/packages/appos/src/api/container.d.mts +210 -0
  139. package/dist/exports/tests/packages/appos/src/api/database.d.mts +99 -0
  140. package/dist/exports/tests/packages/appos/src/api/database.mjs +1 -0
  141. package/dist/exports/tests/packages/appos/src/api/event.d.mts +235 -0
  142. package/dist/exports/tests/packages/appos/src/api/event.mjs +1 -0
  143. package/dist/exports/tests/packages/appos/src/api/i18n.d.mts +34 -0
  144. package/dist/exports/tests/packages/appos/src/api/index.d.mts +27 -0
  145. package/dist/exports/tests/packages/appos/src/api/logger.d.mts +21 -0
  146. package/dist/exports/tests/packages/appos/src/api/mailer.d.mts +70 -0
  147. package/dist/exports/tests/packages/appos/src/api/middleware/error-handler.mjs +1 -0
  148. package/dist/exports/tests/packages/appos/src/api/middleware/health.mjs +1 -0
  149. package/dist/exports/tests/packages/appos/src/api/middleware/i18n.mjs +1 -0
  150. package/dist/exports/tests/packages/appos/src/api/middleware/request-logger.d.mts +24 -0
  151. package/dist/exports/tests/packages/appos/src/api/middleware/request-logger.mjs +1 -0
  152. package/dist/exports/tests/packages/appos/src/api/middleware/shutdown.mjs +1 -0
  153. package/dist/exports/tests/packages/appos/src/api/middleware/timeout.mjs +1 -0
  154. package/dist/exports/tests/packages/appos/src/api/middleware/youch-handler.mjs +1 -0
  155. package/dist/exports/tests/packages/appos/src/api/middleware.d.mts +39 -0
  156. package/dist/exports/tests/packages/appos/src/api/middleware.mjs +1 -0
  157. package/dist/exports/tests/packages/appos/src/api/openapi.d.mts +271 -0
  158. package/dist/exports/tests/packages/appos/src/api/orm.d.mts +13 -0
  159. package/dist/exports/tests/packages/appos/src/api/otel.d.mts +40 -0
  160. package/dist/exports/tests/packages/appos/src/api/redis.d.mts +34 -0
  161. package/dist/exports/tests/packages/appos/src/api/redis.mjs +1 -0
  162. package/dist/exports/tests/packages/appos/src/api/server.mjs +1 -0
  163. package/dist/exports/tests/packages/appos/src/api/storage-schema.d.mts +707 -0
  164. package/dist/exports/tests/packages/appos/src/api/storage.d.mts +506 -0
  165. package/dist/exports/tests/packages/appos/src/api/workflow.d.mts +250 -0
  166. package/dist/exports/tests/packages/appos/src/api/workflow.mjs +1 -0
  167. package/dist/exports/tests/packages/appos/src/api/workflows/extract-blob-metadata.mjs +1 -0
  168. package/dist/exports/tests/packages/appos/src/api/workflows/generate-image-variant.d.mts +99 -0
  169. package/dist/exports/tests/packages/appos/src/api/workflows/generate-image-variant.mjs +1 -0
  170. package/dist/exports/tests/packages/appos/src/api/workflows/generate-preview.mjs +1 -0
  171. package/dist/exports/tests/packages/appos/src/api/workflows/purge-attachment.mjs +1 -0
  172. package/dist/exports/tests/packages/appos/src/api/workflows/purge-audit-logs.mjs +1 -0
  173. package/dist/exports/tests/packages/appos/src/api/workflows/purge-unattached-blobs.mjs +1 -0
  174. package/dist/exports/tests/packages/appos/src/api/workflows/track-db-changes.mjs +1 -0
  175. package/dist/exports/tests/packages/appos/src/constants.mjs +1 -0
  176. package/dist/exports/tests/packages/appos/src/instrumentation.d.mts +7 -0
  177. package/dist/exports/tests/packages/appos/src/instrumentation.mjs +1 -0
  178. package/dist/exports/tests/react.d.mts +2 -0
  179. package/dist/exports/tests/react.mjs +1 -0
  180. package/dist/exports/tests/setup.d.mts +1 -0
  181. package/dist/exports/tests/setup.mjs +1 -0
  182. package/dist/exports/vendors/date.js +1 -0
  183. package/dist/exports/vendors/toolkit.js +1 -0
  184. package/dist/exports/vendors/zod.d.ts +1 -0
  185. package/dist/exports/vendors/zod.js +1 -0
  186. package/dist/exports/vite/index.d.mts +19 -0
  187. package/dist/exports/vite/index.mjs +1 -0
  188. package/dist/exports/vitest/config.d.mts +1 -0
  189. package/dist/exports/vitest/config.mjs +1 -0
  190. package/dist/exports/vitest/globals.d.mts +1 -0
  191. package/dist/exports/vitest/globals.mjs +1 -0
  192. package/dist/exports/vitest/index.d.mts +1 -0
  193. package/dist/exports/vitest/index.mjs +1 -0
  194. package/dist/exports/web/api/auth.d.ts +125 -0
  195. package/dist/exports/web/api/database.d.ts +4 -0
  196. package/dist/exports/web/api/logger.d.ts +1 -0
  197. package/dist/exports/web/auth.d.ts +2388 -0
  198. package/dist/exports/web/auth.js +1 -0
  199. package/dist/exports/web/i18n.d.ts +42 -0
  200. package/dist/exports/web/i18n.js +1 -0
  201. package/dist/exports/web/index.d.ts +6 -0
  202. package/dist/exports/web/index.js +1 -0
  203. package/package.json +138 -98
  204. package/build/bin/main.mjs +0 -2
  205. package/build/exports/cli/index.d.mts +0 -325
  206. package/build/exports/cli/index.mjs +0 -1
  207. package/build/exports/instrumentation/execAsync-DaIUcs6_.mjs +0 -1
  208. package/build/exports/instrumentation/getMachineId-bsd-bB6ipDhm.mjs +0 -1
  209. package/build/exports/instrumentation/getMachineId-darwin-D1Bx5aCe.mjs +0 -2
  210. package/build/exports/instrumentation/getMachineId-linux-D_R9Tla0.mjs +0 -1
  211. package/build/exports/instrumentation/getMachineId-unsupported-BZKPE_Ev.mjs +0 -1
  212. package/build/exports/instrumentation/getMachineId-win-CmPvIqHL.mjs +0 -1
  213. package/build/exports/instrumentation/instrumentation.d.mts +0 -1
  214. package/build/exports/instrumentation/instrumentation.mjs +0 -80
  215. package/build/exports/server/index.d.mts +0 -327
  216. package/build/exports/server/index.mjs +0 -219
  217. package/build/exports/server/react-gPO8Jsy-.mjs +0 -13
  218. package/build/exports/server/server.node-D_9RYjm9.mjs +0 -210
  219. package/build/exports/store/index.d.mts +0 -58
  220. package/build/exports/store/index.mjs +0 -15
  221. package/build/exports/support/datetime.js +0 -1
  222. package/build/exports/support/utils.js +0 -1
  223. package/build/exports/support/zod.d.ts +0 -2
  224. package/build/exports/support/zod.js +0 -23
  225. package/build/exports/test/dist-DAsoCGWk.mjs +0 -348
  226. package/build/exports/test/index.d.mts +0 -3
  227. package/build/exports/test/index.mjs +0 -1
  228. package/build/exports/test/magic-string.es-BWgiB2kd.mjs +0 -14
  229. package/build/exports/test/setup.d.mts +0 -1
  230. package/build/exports/test/setup.mjs +0 -329
  231. /package/{build/exports/support/datetime.d.ts → dist/exports/vendors/date.d.ts} +0 -0
  232. /package/{build/exports/support/utils.d.ts → dist/exports/vendors/toolkit.d.ts} +0 -0
@@ -0,0 +1,250 @@
1
+ import { Container } from "./container.mjs";
2
+ import { z } from "zod";
3
+ import { DBOS } from "@dbos-inc/dbos-sdk";
4
+
5
+ //#region src/api/workflow.d.ts
6
+
7
+ /**
8
+ * Context available to workflow functions.
9
+ */
10
+ interface WorkflowContext<TInput = unknown> {
11
+ /**
12
+ * The application container with access to db, mailer, logger, etc.
13
+ */
14
+ container: Container;
15
+ /**
16
+ * The validated input passed to this workflow.
17
+ */
18
+ input: TInput;
19
+ /**
20
+ * Execute a checkpointed step within the workflow.
21
+ * Steps are retried on failure and their results are durably stored.
22
+ *
23
+ * @param name - Unique name for this step within the workflow
24
+ * @param fn - The step function to execute
25
+ * @returns The result of the step function
26
+ */
27
+ step<T>(name: string, fn: () => Promise<T>): Promise<T>;
28
+ /**
29
+ * The unique ID of this workflow execution.
30
+ */
31
+ workflowId: string;
32
+ }
33
+ /**
34
+ * Context available to scheduled workflow functions.
35
+ */
36
+ interface ScheduledWorkflowContext {
37
+ /**
38
+ * The application container with access to db, mailer, logger, etc.
39
+ */
40
+ container: Container;
41
+ /**
42
+ * The time this workflow execution was scheduled for.
43
+ */
44
+ scheduledTime: Date;
45
+ /**
46
+ * Execute a checkpointed step within the workflow.
47
+ * Steps are retried on failure and their results are durably stored.
48
+ *
49
+ * @param name - Unique name for this step within the workflow
50
+ * @param fn - The step function to execute
51
+ * @returns The result of the step function
52
+ */
53
+ step<T>(name: string, fn: () => Promise<T>): Promise<T>;
54
+ /**
55
+ * The unique ID of this workflow execution.
56
+ */
57
+ workflowId: string;
58
+ }
59
+ /**
60
+ * Handle to a running or completed workflow.
61
+ */
62
+ interface WorkflowHandle<TOutput> {
63
+ /**
64
+ * Get the current status of the workflow.
65
+ */
66
+ getStatus(): Promise<unknown>;
67
+ /**
68
+ * Wait for the workflow to complete and return its result.
69
+ */
70
+ getResult(): Promise<TOutput>;
71
+ /**
72
+ * The unique ID of this workflow execution.
73
+ */
74
+ workflowId: string;
75
+ }
76
+ /**
77
+ * Options for defining a workflow.
78
+ */
79
+ interface DefineWorkflowOptions<TInput extends z.ZodType, TOutput> {
80
+ /**
81
+ * Optional configuration for the workflow.
82
+ */
83
+ config?: {
84
+ /**
85
+ * Maximum number of times to attempt recovery after failure.
86
+ */
87
+ maxRecoveryAttempts?: number;
88
+ };
89
+ /**
90
+ * Zod schema for validating workflow input.
91
+ */
92
+ input: TInput;
93
+ /**
94
+ * The workflow function to execute.
95
+ *
96
+ * @param ctx - Workflow context with container, input, and step helper
97
+ * @returns The workflow result
98
+ */
99
+ run: (ctx: WorkflowContext<z.infer<TInput>>) => Promise<TOutput>;
100
+ }
101
+ /**
102
+ * Defines a durable workflow that can be triggered with type-safe input.
103
+ *
104
+ * Workflows are:
105
+ * - Durable: Automatically resume after crashes or restarts
106
+ * - Type-safe: Input and output types are inferred from the schema
107
+ * - Container-aware: Access to db, mailer, logger via ctx.container
108
+ *
109
+ * @example
110
+ * ```typescript
111
+ * // api/workflows/send-welcome-email.ts
112
+ * export default defineWorkflow({
113
+ * input: z.object({
114
+ * userId: z.string(),
115
+ * email: z.string().email(),
116
+ * }),
117
+ * async run(ctx) {
118
+ * const user = await ctx.container.db.primary.query.users.findFirst({
119
+ * where: eq(users.id, ctx.input.userId),
120
+ * });
121
+ *
122
+ * await ctx.container.mailer.send({
123
+ * to: ctx.input.email,
124
+ * subject: "Welcome!",
125
+ * });
126
+ *
127
+ * return { sent: true };
128
+ * },
129
+ * });
130
+ *
131
+ * // Triggering from a route:
132
+ * import sendWelcomeEmail from "#api/workflows/send-welcome-email.ts";
133
+ * const handle = await sendWelcomeEmail.start({ userId: "123", email: "..." });
134
+ * ```
135
+ */
136
+ declare function defineWorkflow<TInput extends z.ZodType, TOutput>(options: DefineWorkflowOptions<TInput, TOutput>): {
137
+ /**
138
+ * The Zod schema for validating input.
139
+ */
140
+ inputSchema: TInput;
141
+ /**
142
+ * The workflow name (set during registration from filename).
143
+ */
144
+ readonly name: string | null;
145
+ /**
146
+ * Register this workflow with DBOS. Called by the workflow loader.
147
+ *
148
+ * @param c - The application container
149
+ * @param name - The workflow name (derived from filename)
150
+ * @param dbos - The DBOS instance to use for registration
151
+ */
152
+ register(c: Container, name: string, dbos: typeof DBOS): void;
153
+ /**
154
+ * Start this workflow with the given input.
155
+ *
156
+ * @param input - Input matching the workflow's input schema
157
+ * @returns A handle to track and retrieve the workflow result
158
+ */
159
+ start(input: z.infer<TInput>): Promise<WorkflowHandle<TOutput>>;
160
+ };
161
+ /**
162
+ * Options for defining a scheduled workflow.
163
+ */
164
+ interface DefineScheduledWorkflowOptions {
165
+ /**
166
+ * Cron expression for when to run the workflow.
167
+ * Supports 5-spot (minute hour day month weekday) or
168
+ * 6-spot (second minute hour day month weekday) format.
169
+ *
170
+ * Examples:
171
+ * - "0 9 * * *" - Every day at 9am
172
+ * - "0,30 * * * *" - Every 30 minutes
173
+ * - "0 0 * * * *" - Every hour (6-spot with seconds)
174
+ */
175
+ crontab: string;
176
+ /**
177
+ * The workflow function to execute on schedule.
178
+ *
179
+ * @param ctx - Workflow context with container, scheduledTime, and step helper
180
+ */
181
+ run: (ctx: ScheduledWorkflowContext) => Promise<void>;
182
+ }
183
+ /**
184
+ * Defines a scheduled workflow that runs on a cron schedule.
185
+ *
186
+ * @example
187
+ * ```typescript
188
+ * // api/workflows/daily-report.ts
189
+ * export default defineScheduledWorkflow({
190
+ * crontab: "0 9 * * *", // 9am daily
191
+ * async run(ctx) {
192
+ * const stats = await ctx.container.db.primary.query.stats.findMany();
193
+ * await ctx.container.mailer.send({
194
+ * to: "team@company.com",
195
+ * subject: `Daily Report - ${ctx.scheduledTime.toDateString()}`,
196
+ * });
197
+ * },
198
+ * });
199
+ * ```
200
+ */
201
+ declare function defineScheduledWorkflow(options: DefineScheduledWorkflowOptions): {
202
+ /**
203
+ * The cron expression for this workflow.
204
+ */
205
+ crontab: string;
206
+ /**
207
+ * The workflow name (set during registration from filename).
208
+ */
209
+ readonly name: string | null;
210
+ /**
211
+ * Register this workflow with DBOS. Called by the workflow loader.
212
+ *
213
+ * @param c - The application container
214
+ * @param name - The workflow name (derived from filename)
215
+ * @param dbos - The DBOS instance to use for registration
216
+ */
217
+ register(c: Container, name: string, dbos: typeof DBOS): void;
218
+ };
219
+ /**
220
+ * Options for loading workflows.
221
+ */
222
+ interface LoadWorkflowsOptions {
223
+ /**
224
+ * The application container.
225
+ */
226
+ container: Container;
227
+ /**
228
+ * The DBOS instance to use for registration.
229
+ */
230
+ dbos: typeof DBOS;
231
+ /**
232
+ * Optional custom workflows directory path.
233
+ */
234
+ workflowsDir?: string;
235
+ }
236
+ /**
237
+ * Auto-discovers and registers all workflows.
238
+ *
239
+ * Algorithm:
240
+ * 1. Register built-in workflows (extractBlobMetadata, generateImageVariant, etc.)
241
+ * 2. Register scheduled workflows (purgeAuditLogs, purgeUnattachedBlobs)
242
+ * 3. Glob all .ts files in the directory (excluding test files)
243
+ * 4. Import each module's default export
244
+ * 5. If it has a register method, call register(container, name, dbos)
245
+ *
246
+ * @param opts - Load workflows options
247
+ */
248
+ declare function loadWorkflows(opts: LoadWorkflowsOptions): Promise<void>;
249
+ //#endregion
250
+ export { ScheduledWorkflowContext, WorkflowContext, WorkflowHandle, defineScheduledWorkflow, defineWorkflow, loadWorkflows };
@@ -0,0 +1 @@
1
+ import{glob as e}from"node:fs/promises";import{basename as t,join as n}from"node:path";import"es-toolkit";function r(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 i(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{i as defineScheduledWorkflow,r as defineWorkflow};
@@ -0,0 +1 @@
1
+ import{defineWorkflow as e}from"../workflow.mjs";import{join as t}from"node:path";import{ALL_FORMATS as n,BlobSource as r,Input as i}from"mediabunny";import a from"sharp";import o from"zod";const s=e({input:o.object({blobId:o.string()}),async run({container:e,input:{blobId:o},step:s}){let c=await s(`fetch-blob`,async()=>e.storage.primary.getBlob(o));if(!c)throw Error(`Blob ${o} not found`);let l=await s(`download-blob`,async()=>e.storage.primary.downloadBlob(o));if(!l)throw Error(`Failed to download blob ${o}`);let u={};return c.contentType?.startsWith(`image/`)?u=await s(`extract-image-metadata`,async()=>{let e=await a(l).metadata();return{width:e.width,height:e.height,format:e.format,hasAlpha:e.hasAlpha,space:e.space}}):c.contentType?.startsWith(`video/`)||c.contentType?.startsWith(`audio/`)?u=await s(`extract-media-metadata`,async()=>{let e=new Uint8Array(l),t=new i({source:new r(new Blob([e],{type:c.contentType||`video/mp4`})),formats:n}),a=await t.computeDuration(),o=await t.getMetadataTags(),s={},u={},d=!1,f=!1;try{let e=await t.getPrimaryVideoTrack();if(e){d=!0;let t=e.displayWidth&&e.displayHeight?e.displayWidth/e.displayHeight:null;s={width:e.displayWidth,height:e.displayHeight,rotation:e.rotation,angle:e.rotation,displayAspectRatio:t}}}catch{}try{let e=await t.getPrimaryAudioTrack();e&&(f=!0,u={sampleRate:e.sampleRate,channels:e.numberOfChannels})}catch{}return{duration:a,video:d,audio:f,...s,...u,tags:o}}):c.contentType===`application/pdf`&&(u=await s(`extract-pdf-metadata`,async()=>{try{let e=await import(`pdfjs-dist/legacy/build/pdf.mjs`),n=`${t(process.cwd(),`node_modules/pdfjs-dist/standard_fonts`)}/`,r=await e.getDocument({data:new Uint8Array(l),standardFontDataUrl:n}).promise,i=await r.getMetadata(),a=(await r.getPage(1)).getViewport({scale:1}),o=i.info;return{pageCount:r.numPages,width:a.width,height:a.height,title:o?.Title||null,author:o?.Author||null,subject:o?.Subject||null,keywords:o?.Keywords||null,creator:o?.Creator||null,producer:o?.Producer||null,creationDate:o?.CreationDate||null,modificationDate:o?.ModDate||null,pdfVersion:o?.PDFFormatVersion||null}}catch(t){return e.logger.error({error:t,errorMessage:t instanceof Error?t.message:String(t),errorStack:t instanceof Error?t.stack:void 0,errorCode:t?.code,blobId:o},`Failed to extract PDF metadata`),{error:`Failed to extract PDF metadata`,errorMessage:t instanceof Error?t.message:String(t)}}})),await s(`save-metadata`,async()=>{await e.storage.primary.updateBlobMetadata(o,{...u,analyzed:!0})}),e.logger.info({blobId:o,metadata:u},`Metadata extracted`),{...u,analyzed:!0}}});export{s as extractBlobMetadata};
@@ -0,0 +1,99 @@
1
+ import "../workflow.mjs";
2
+ import "../index.mjs";
3
+ import { z } from "zod";
4
+
5
+ //#region src/api/workflows/generate-image-variant.d.ts
6
+ /**
7
+ * Resize options schema for image transformations.
8
+ */
9
+ declare const resizeSchema: z.ZodObject<{
10
+ width: z.ZodOptional<z.ZodNumber>;
11
+ height: z.ZodOptional<z.ZodNumber>;
12
+ fit: z.ZodOptional<z.ZodEnum<{
13
+ fill: "fill";
14
+ cover: "cover";
15
+ contain: "contain";
16
+ inside: "inside";
17
+ outside: "outside";
18
+ }>>;
19
+ position: z.ZodOptional<z.ZodEnum<{
20
+ left: "left";
21
+ right: "right";
22
+ top: "top";
23
+ "right top": "right top";
24
+ "right bottom": "right bottom";
25
+ bottom: "bottom";
26
+ "left bottom": "left bottom";
27
+ "left top": "left top";
28
+ centre: "centre";
29
+ }>>;
30
+ kernel: z.ZodOptional<z.ZodEnum<{
31
+ nearest: "nearest";
32
+ linear: "linear";
33
+ cubic: "cubic";
34
+ mitchell: "mitchell";
35
+ lanczos2: "lanczos2";
36
+ lanczos3: "lanczos3";
37
+ }>>;
38
+ }, z.core.$strip>;
39
+ /**
40
+ * Image transformations schema.
41
+ * Supports resize, rotate, flip, flop, sharpen, blur, grayscale, format conversion.
42
+ */
43
+ declare const transformationsSchema: z.ZodObject<{
44
+ resize: z.ZodOptional<z.ZodObject<{
45
+ width: z.ZodOptional<z.ZodNumber>;
46
+ height: z.ZodOptional<z.ZodNumber>;
47
+ fit: z.ZodOptional<z.ZodEnum<{
48
+ fill: "fill";
49
+ cover: "cover";
50
+ contain: "contain";
51
+ inside: "inside";
52
+ outside: "outside";
53
+ }>>;
54
+ position: z.ZodOptional<z.ZodEnum<{
55
+ left: "left";
56
+ right: "right";
57
+ top: "top";
58
+ "right top": "right top";
59
+ "right bottom": "right bottom";
60
+ bottom: "bottom";
61
+ "left bottom": "left bottom";
62
+ "left top": "left top";
63
+ centre: "centre";
64
+ }>>;
65
+ kernel: z.ZodOptional<z.ZodEnum<{
66
+ nearest: "nearest";
67
+ linear: "linear";
68
+ cubic: "cubic";
69
+ mitchell: "mitchell";
70
+ lanczos2: "lanczos2";
71
+ lanczos3: "lanczos3";
72
+ }>>;
73
+ }, z.core.$strip>>;
74
+ rotate: z.ZodOptional<z.ZodNumber>;
75
+ flip: z.ZodOptional<z.ZodBoolean>;
76
+ flop: z.ZodOptional<z.ZodBoolean>;
77
+ sharpen: z.ZodOptional<z.ZodBoolean>;
78
+ blur: z.ZodOptional<z.ZodNumber>;
79
+ grayscale: z.ZodOptional<z.ZodBoolean>;
80
+ format: z.ZodOptional<z.ZodEnum<{
81
+ jpeg: "jpeg";
82
+ png: "png";
83
+ webp: "webp";
84
+ avif: "avif";
85
+ gif: "gif";
86
+ }>>;
87
+ quality: z.ZodOptional<z.ZodNumber>;
88
+ preview: z.ZodOptional<z.ZodLiteral<true>>;
89
+ }, z.core.$strip>;
90
+ /**
91
+ * Types for image transformations.
92
+ */
93
+ type ImageTransformations = z.infer<typeof transformationsSchema>;
94
+ /**
95
+ * Types for resize options.
96
+ */
97
+ type ResizeOptions = z.infer<typeof resizeSchema>;
98
+ //#endregion
99
+ export { ImageTransformations, ResizeOptions, resizeSchema, transformationsSchema };
@@ -0,0 +1 @@
1
+ import{defineWorkflow as e}from"../workflow.mjs";import t from"sharp";import{z as n}from"zod";const r=n.object({width:n.number().optional(),height:n.number().optional(),fit:n.enum([`cover`,`contain`,`fill`,`inside`,`outside`]).optional(),position:n.enum([`top`,`right top`,`right`,`right bottom`,`bottom`,`left bottom`,`left`,`left top`,`centre`]).optional(),kernel:n.enum([`nearest`,`linear`,`cubic`,`mitchell`,`lanczos2`,`lanczos3`]).optional()}),i=n.object({resize:r.optional(),rotate:n.number().optional(),flip:n.boolean().optional(),flop:n.boolean().optional(),sharpen:n.boolean().optional(),blur:n.number().optional(),grayscale:n.boolean().optional(),format:n.enum([`jpeg`,`png`,`webp`,`avif`,`gif`]).optional(),quality:n.number().min(1).max(100).optional(),preview:n.literal(!0).optional()}),a=e({input:n.object({blobId:n.string(),transformations:i}),async run({container:e,input:{blobId:n,transformations:r},step:i}){if(!await i(`fetch-blob`,async()=>e.storage.primary.getBlob(n)))throw Error(`Blob ${n} not found`);let a=await i(`download-blob`,async()=>e.storage.primary.downloadBlob(n));if(!a)throw Error(`Failed to download blob ${n}`);let o=await i(`apply-transformations`,async()=>{let e=t(a);return r.resize&&(e=e.resize({width:r.resize.width,height:r.resize.height,fit:r.resize.fit,position:r.resize.position,kernel:r.resize.kernel})),r.rotate!==void 0&&(e=e.rotate(r.rotate)),r.flip&&(e=e.flip()),r.flop&&(e=e.flop()),r.sharpen&&(e=e.sharpen()),r.blur!==void 0&&(e=e.blur(r.blur)),r.grayscale&&(e=e.grayscale()),r.format&&(e=e.toFormat(r.format,{quality:r.quality})),e.toBuffer()}),s=await i(`store-variant`,async()=>e.storage.primary.createVariant(n,r,o));return e.logger.info({blobId:n,variantId:s.id},`Image variant generated`),s}});export{a as generateImageVariant};
@@ -0,0 +1 @@
1
+ import{defineWorkflow as e}from"../workflow.mjs";import{join as t}from"node:path";import n from"sharp";import r from"zod";import{spawn as i}from"node:child_process";import{createCanvas as a}from"canvas";const o=e({input:r.object({blobId:r.string(),timeInSeconds:r.number().optional()}),async run({container:e,input:{blobId:r,timeInSeconds:o=1},step:s}){let c=await s(`fetch-blob`,async()=>e.storage.primary.getBlob(r));if(!c)throw Error(`Blob ${r} not found`);let l=await s(`download-blob`,async()=>e.storage.primary.downloadBlob(r));if(!l)throw Error(`Failed to download blob ${r}`);let u=null;if(c.contentType?.startsWith(`video/`))u=await s(`generate-video-preview`,async()=>new Promise((t,a)=>{try{let s=i(`ffmpeg`,[`-i`,`pipe:0`,`-ss`,o.toString(),`-frames:v`,`1`,`-f`,`image2pipe`,`-c:v`,`png`,`pipe:1`]),c=[],u=[];s.stdout.on(`data`,e=>{c.push(e)}),s.stderr.on(`data`,e=>{u.push(e)}),s.on(`close`,async i=>{if(i===0)try{t(await n(Buffer.concat(c)).jpeg({quality:80}).toBuffer())}catch(t){e.logger.error({error:t,blobId:r},`Failed to convert video frame to JPEG`),a(t)}else{let t=Buffer.concat(u).toString(),n=Error(`FFmpeg exited with code ${i}: ${t}`);e.logger.error({error:n,blobId:r,code:i,stderr:t},`Failed to generate video preview`),a(n)}}),s.on(`error`,t=>{e.logger.error({error:t,blobId:r},`Failed to spawn FFmpeg process`),a(t)}),s.stdin.on(`error`,t=>{t.code!==`EPIPE`&&e.logger.error({error:t,blobId:r},`Failed to write to FFmpeg stdin`)}),s.stdin.write(l),s.stdin.end()}catch(t){e.logger.error({error:t,blobId:r},`Failed to generate video preview`),a(t)}}));else if(c.contentType===`application/pdf`)u=await s(`generate-pdf-preview`,async()=>{try{let e=await import(`pdfjs-dist/legacy/build/pdf.mjs`),r=`${t(process.cwd(),`node_modules/pdfjs-dist/standard_fonts`)}/`,i=await(await e.getDocument({data:new Uint8Array(l),standardFontDataUrl:r}).promise).getPage(1),o=i.getViewport({scale:2}),s=a(o.width,o.height),c=s.getContext(`2d`);return await i.render({canvasContext:c,viewport:o,canvas:s}).promise,await n(s.toBuffer(`image/png`)).resize(800,800,{fit:`inside`,withoutEnlargement:!0}).jpeg({quality:85}).toBuffer()}catch(t){throw e.logger.error({error:t,errorMessage:t instanceof Error?t.message:String(t),errorStack:t instanceof Error?t.stack:void 0,errorCode:t?.code,blobId:r},`Failed to generate PDF preview`),t}});else if(c.contentType?.startsWith(`image/`))u=await s(`generate-image-preview`,async()=>await n(l).resize(800,800,{fit:`inside`,withoutEnlargement:!0}).jpeg({quality:85}).toBuffer());else throw Error(`Preview generation not supported for content type: ${c.contentType}`);let d=await s(`store-preview`,async()=>await e.storage.primary.createVariant(r,{preview:!0},u));return e.logger.info({blobId:r,previewId:d.id,contentType:c.contentType},`Preview generated`),d}});export{o as generatePreview};
@@ -0,0 +1 @@
1
+ import{defineWorkflow as e}from"../workflow.mjs";import t from"zod";const n=e({input:t.object({attachmentIds:t.array(t.string()).min(1)}),async run({container:e,input:{attachmentIds:t},step:n}){let r=await n(`fetch-attachments`,async()=>(await e.storage.primary.getAttachmentsByIds(t)).filter(e=>e.blob!==null).map(e=>({attachmentId:e.id,blobId:e.blob.id})));return await n(`delete-attachments`,async()=>{for(let{attachmentId:t}of r)await e.storage.primary.deleteAttachment(t)}),await n(`delete-blobs`,async()=>{for(let{blobId:t}of r)await e.storage.primary.deleteBlob(t)}),e.logger.info({attachmentIds:t,blobCount:r.length},`Attachments and blobs purged`),{purgedCount:r.length}}});export{n as purgeAttachment};
@@ -0,0 +1 @@
1
+ import{defineScheduledWorkflow as e}from"../workflow.mjs";import{defineAuthSchema as t}from"../auth-schema.mjs";import{lt as n}from"drizzle-orm";const r=t();function i(t=`0 0 * * *`){return e({crontab:t,async run({container:e,step:t,scheduledTime:i}){let a=e.auth.auditLog?.retentionDays??90,o=new Date(i);o.setDate(o.getDate()-a);let s=o.toISOString(),c=await t(`delete-old-logs`,async()=>{let{auditLogs:t}=r.tables;return(await e.db.primary.delete(t).where(n(t.createdAt,s)).returning({id:t.id})).length});e.logger.info({deletedCount:c,retentionDays:a,cutoffDate:s},`Audit log purge completed`)}})}export{i as definePurgeAuditLogs};
@@ -0,0 +1 @@
1
+ import{defineScheduledWorkflow as e}from"../workflow.mjs";function t(t=`0 0 * * *`){return e({crontab:t,async run({container:e,step:t}){let n=new Date(Date.now()-2880*60*1e3).toISOString(),r=await t(`fetch-unattached-blobs`,async()=>e.storage.primary.getUnattachedBlobs({olderThan:n})),i=await t(`fetch-pending-blobs`,async()=>e.storage.primary.getPendingBlobs(n)),a=[...r,...i],o=0;for(let n of a)await t(`delete-blob`,async()=>{await e.storage.primary.deleteBlob(n.id),o++});e.logger.info({purgedCount:o,unattachedCount:r.length,pendingCount:i.length},`Orphaned blobs purged`)}})}export{t as definePurgeUnattachedBlobs};
@@ -0,0 +1 @@
1
+ import{defineWorkflow as e}from"../workflow.mjs";import{defineAuthSchema as t}from"../auth-schema.mjs";import{dbChangesEvent as n}from"../event.mjs";import{z as r}from"zod";const i=t(),a=r.object({changes:r.array(r.object({_table:r.string(),old:r.record(r.string(),r.unknown()).nullable(),new:r.record(r.string(),r.unknown()).nullable()})),dbName:r.string(),organizationId:r.string().nullable(),requestId:r.string(),sessionId:r.string().nullable(),userId:r.string().nullable()});function o(e){return e.old===null?`INSERT`:e.new===null?`DELETE`:`UPDATE`}const s=e({input:a,async run({container:e,step:t,input:r}){let{dbName:a,changes:s,organizationId:c,userId:l,sessionId:u,requestId:d}=r;if(s.length===0)return{processed:0,audited:0,published:0};let f=new Date().toISOString(),p=0,m=0;for(let r of s){let s=r._table,h=o(r),g=`${a}.${s}`;e.auth.shouldAudit(g)&&(await t(`audit:${g}`,async()=>{await e.db.primary.insert(i.tables.auditLogs).values({tableName:g,action:h,oldData:r.old,newData:r.new,organizationId:c,userId:l,sessionId:u,requestId:d,createdAt:f})}),p++),await t(`event:${g}`,async()=>{await n.emit({action:h,oldData:r.old,newData:r.new,organizationId:c,tableName:g,timestamp:f,userId:l})}),m++}return{processed:s.length,audited:p,published:m}}});export{s as trackDbChanges};
@@ -0,0 +1 @@
1
+ const e=`api`,t=`databases`;export{e as APPOS_DIR,t as DATABASES_DIR};
@@ -0,0 +1,7 @@
1
+ export * from "@opentelemetry/api";
2
+
3
+ //#region src/instrumentation.d.ts
4
+
5
+ import * as import__opentelemetry_api from "@opentelemetry/api";
6
+ //#endregion
7
+ export { import__opentelemetry_api as instrumentation_d_exports };
@@ -0,0 +1 @@
1
+ import{__reExport as e}from"../../../_virtual/rolldown_runtime.mjs";import{register as t}from"node:module";import{getNodeAutoInstrumentations as n}from"@opentelemetry/auto-instrumentations-node";import{OTLPTraceExporter as r}from"@opentelemetry/exporter-trace-otlp-http";import{PinoInstrumentation as i}from"@opentelemetry/instrumentation-pino";import{resourceFromAttributes as a}from"@opentelemetry/resources";import{NodeSDK as o}from"@opentelemetry/sdk-node";import{BatchSpanProcessor as s}from"@opentelemetry/sdk-trace-node";import{ATTR_SERVICE_NAME as c,ATTR_SERVICE_VERSION as l}from"@opentelemetry/semantic-conventions";export*from"@opentelemetry/api";var u={};import*as d from"@opentelemetry/api";e(u,d),t(`@opentelemetry/instrumentation/hook.mjs`,import.meta.url);const f={name:process.env.APP_NAME||`appos`,version:process.env.APP_VERSION||`development`};new o({resource:a({[c]:f.name,[l]:f.version}),spanProcessors:[new s(new r({url:process.env.OTEL_EXPORTER_OTLP_ENDPOINT||`http://localhost:4318/v1/traces`,headers:process.env.OTEL_EXPORTER_OTLP_HEADERS?JSON.parse(process.env.OTEL_EXPORTER_OTLP_HEADERS):void 0}))],instrumentations:[n({"@opentelemetry/instrumentation-fs":{enabled:!1},"@opentelemetry/instrumentation-dns":{enabled:!1}}),new i({logHook:(e,t)=>{t[`service.name`]=f.name}})]}).start();export{u as instrumentation_exports};
@@ -0,0 +1,2 @@
1
+ export * from "@testing-library/react";
2
+ export * from "@testing-library/user-event";
@@ -0,0 +1 @@
1
+ export*from"@testing-library/react";export*from"@testing-library/user-event";export{};
@@ -0,0 +1 @@
1
+ import "@testing-library/jest-dom/vitest";
@@ -0,0 +1 @@
1
+ import{cleanup as e}from"@testing-library/react";import"@testing-library/jest-dom/vitest";import{Blob as t}from"node:buffer";var n=class extends TextEncoder{encode(e){if(typeof e!=`string`)throw TypeError("`input` must be a string");let t=decodeURIComponent(encodeURIComponent(e)),n=new Uint8Array(t.length),r=t.split(``);for(let e=0;e<r.length;e++)n[e]=t[e].charCodeAt(0);return n}};global.TextEncoder=n,afterEach(()=>{e()}),global.Blob=t,typeof window<`u`&&(Object.defineProperty(window,`matchMedia`,{writable:!0,value:vi.fn().mockImplementation(e=>({matches:!1,media:e,onchange:null,addListener:vi.fn(),removeListener:vi.fn(),addEventListener:vi.fn(),removeEventListener:vi.fn(),dispatchEvent:vi.fn()}))}),Object.defineProperty(window,`scrollTo`,{writable:!0,value:vi.fn()})),typeof Element<`u`&&(Object.defineProperty(Element.prototype,`scrollTo`,{writable:!0,value:vi.fn()}),Object.defineProperty(Element.prototype,`scrollIntoView`,{writable:!0,value:vi.fn()}),Element.prototype.hasPointerCapture||(Element.prototype.hasPointerCapture=vi.fn().mockReturnValue(!1)),Element.prototype.releasePointerCapture||(Element.prototype.releasePointerCapture=vi.fn()),Element.prototype.setPointerCapture||(Element.prototype.setPointerCapture=vi.fn())),global.ResizeObserver=class{observe=vi.fn();unobserve=vi.fn();disconnect=vi.fn()},global.IntersectionObserver=class{root=null;rootMargin=``;scrollMargin=``;thresholds=[];observe=vi.fn();unobserve=vi.fn();disconnect=vi.fn();takeRecords=vi.fn().mockReturnValue([])},globalThis.URL||(globalThis.URL=class e{constructor(t,n){this.href=t,n&&(this.href=new e(t,n).href)}toString(){return this.href}}),globalThis.fetch||(globalThis.fetch=vi.fn().mockImplementation(()=>Promise.resolve({ok:!0,json:()=>Promise.resolve({}),text:()=>Promise.resolve(``)})));export{};
@@ -0,0 +1 @@
1
+ export*from"date-fns";
@@ -0,0 +1 @@
1
+ export*from"es-toolkit";
@@ -0,0 +1 @@
1
+ export * from "zod";
@@ -0,0 +1 @@
1
+ export*from"zod";
@@ -0,0 +1,19 @@
1
+ import react from "@vitejs/plugin-react";
2
+ import { i18nextHMRPlugin } from "i18next-hmr/vite";
3
+ import { PluginOption } from "vite";
4
+ import babel from "vite-plugin-babel";
5
+ export * from "vite";
6
+
7
+ //#region src/vite/index.d.ts
8
+
9
+ /**
10
+ * Vite plugin that fixes SSR module resolution issues with Vitest.
11
+ *
12
+ * Removes the "module" export condition from SSR resolve configuration
13
+ * to fix compatibility issues with packages like @smithy/core (AWS SDK).
14
+ *
15
+ * @see https://github.com/vitest-dev/vitest/issues/7794
16
+ */
17
+ declare function vitestSSRFix(): PluginOption;
18
+ //#endregion
19
+ export { babel, i18nextHMRPlugin, react, vitestSSRFix };
@@ -0,0 +1 @@
1
+ import e from"@vitejs/plugin-react";import{i18nextHMRPlugin as t}from"i18next-hmr/vite";import n from"vite-plugin-babel";export*from"vite";function r(){return{name:`vitest-ssr-fix`,enforce:`post`,config(e){e.ssr?.resolve?.conditions&&(e.ssr.resolve.conditions=e.ssr.resolve.conditions.filter(e=>e!==`module`))}}}export{n as babel,t as i18nextHMRPlugin,e as react,r as vitestSSRFix};
@@ -0,0 +1 @@
1
+ export * from "vitest/config";
@@ -0,0 +1 @@
1
+ export*from"vitest/config";export{};
@@ -0,0 +1 @@
1
+ export * from "vitest/globals";
@@ -0,0 +1 @@
1
+ export*from"vitest/globals";export{};
@@ -0,0 +1 @@
1
+ export * from "vitest";
@@ -0,0 +1 @@
1
+ export*from"vitest";export{};
@@ -0,0 +1,125 @@
1
+ import "./database.js";
2
+ import { Role, createAccessControl } from "better-auth/plugins/access";
3
+ import "zod";
4
+
5
+ //#region src/api/auth.d.ts
6
+
7
+ /**
8
+ * Type for access controller created via createAccessControl().
9
+ * Used for RBAC on both server and client.
10
+ */
11
+ type AccessController = ReturnType<typeof createAccessControl>;
12
+ /**
13
+ * Type for roles created via ac.newRole().
14
+ * Uses Role type from better-auth for compatibility.
15
+ */
16
+ type AccessControlRoles = Record<string, Role>;
17
+ /**
18
+ * Neutral auth configuration - shared between server and client.
19
+ * Contains ONLY fields that affect both sides (UI + server features).
20
+ *
21
+ * PRESENCE-BASED CONFIG: If a key exists, it's enabled. No redundant `enabled` fields.
22
+ * Server-only fields (appName, session) are passed via DefineAuthOptions.
23
+ */
24
+ interface AuthConfig {
25
+ /**
26
+ * Base URL where auth server is hosted.
27
+ *
28
+ * @default "" (same origin - client uses relative URLs)
29
+ * @example "http://localhost:8000" for cross-origin
30
+ */
31
+ baseURL?: string;
32
+ /**
33
+ * Base path for auth routes.
34
+ *
35
+ * @default "/auth"
36
+ */
37
+ basePath?: string;
38
+ /** Authentication methods - if defined, it's enabled */
39
+ methods?: {
40
+ /** Email/password auth. If defined, enabled. */
41
+ emailPassword?: {
42
+ requireEmailVerification?: boolean;
43
+ minPasswordLength?: number;
44
+ maxPasswordLength?: number;
45
+ };
46
+ /** Magic link auth. If defined, enabled. */
47
+ magicLink?: {
48
+ expiresIn?: number;
49
+ };
50
+ /** Passkey auth. If defined (even as empty object), enabled. */
51
+ passkey?: Record<string, never>;
52
+ /** Phone OTP auth. If defined, enabled. */
53
+ phoneOtp?: {
54
+ otpLength?: number;
55
+ expiresIn?: number;
56
+ };
57
+ /** Email OTP auth. If defined, enabled. */
58
+ emailOtp?: {
59
+ otpLength?: number;
60
+ expiresIn?: number;
61
+ };
62
+ };
63
+ /** OAuth providers - true = enabled, undefined/false = disabled */
64
+ oauth?: {
65
+ google?: boolean;
66
+ github?: boolean;
67
+ apple?: boolean;
68
+ facebook?: boolean;
69
+ };
70
+ /** Plugins - if defined, it's enabled */
71
+ plugins?: {
72
+ /** Admin plugin. If defined, enabled. Includes RBAC for both server and client. */
73
+ admin?: {
74
+ defaultRole?: string;
75
+ adminRoles?: string[];
76
+ /** Access controller created via createAccessControl() - shared between server and client */
77
+ ac: AccessController;
78
+ /** Role definitions created via ac.newRole() - shared between server and client */
79
+ roles: AccessControlRoles;
80
+ };
81
+ /** API key plugin. If defined, enabled. */
82
+ apiKey?: {
83
+ defaultPrefix?: string;
84
+ defaultKeyLength?: number;
85
+ rateLimit?: {
86
+ maxRequests?: number;
87
+ timeWindow?: number;
88
+ };
89
+ };
90
+ /** Two-factor plugin. If defined, enabled. Sub-features also presence-based. */
91
+ twoFactor?: {
92
+ issuer?: string;
93
+ totp?: {
94
+ digits?: 6 | 8;
95
+ period?: number;
96
+ };
97
+ otp?: boolean;
98
+ backupCodes?: {
99
+ amount?: number;
100
+ length?: number;
101
+ };
102
+ };
103
+ /** Multi-session plugin. If defined, enabled. */
104
+ multiSession?: {
105
+ maximumSessions?: number;
106
+ };
107
+ /** Username plugin. If defined, enabled. */
108
+ username?: {
109
+ minUsernameLength?: number;
110
+ maxUsernameLength?: number;
111
+ };
112
+ /** Anonymous auth plugin. If defined, enabled. */
113
+ anonymous?: {
114
+ emailDomainName?: string;
115
+ };
116
+ /** SSO plugin. If defined, enabled. Import from @better-auth/sso */
117
+ sso?: {
118
+ providersLimit?: number;
119
+ trustEmailVerified?: boolean;
120
+ domainVerification?: boolean;
121
+ };
122
+ };
123
+ }
124
+ //#endregion
125
+ export { AuthConfig };
@@ -0,0 +1,4 @@
1
+ import "./logger.js";
2
+ import "drizzle-orm";
3
+ import "drizzle-orm/node-postgres";
4
+ import "pg";
@@ -0,0 +1 @@
1
+ import "pino";