alepha 0.20.7 → 0.21.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 (230) hide show
  1. package/README.md +30 -19
  2. package/assets/swagger-ui/swagger-ui-bundle.js +1 -1
  3. package/dist/api/audits/index.d.ts +2 -2
  4. package/dist/api/audits/index.d.ts.map +1 -1
  5. package/dist/api/files/index.browser.js +25 -0
  6. package/dist/api/files/index.browser.js.map +1 -1
  7. package/dist/api/files/index.d.ts +72 -2
  8. package/dist/api/files/index.d.ts.map +1 -1
  9. package/dist/api/files/index.js +82 -7
  10. package/dist/api/files/index.js.map +1 -1
  11. package/dist/api/jobs/index.d.ts +7 -5
  12. package/dist/api/jobs/index.d.ts.map +1 -1
  13. package/dist/api/jobs/index.js +4 -2
  14. package/dist/api/jobs/index.js.map +1 -1
  15. package/dist/api/keys/index.d.ts +3 -0
  16. package/dist/api/keys/index.d.ts.map +1 -1
  17. package/dist/api/keys/index.js +2 -0
  18. package/dist/api/keys/index.js.map +1 -1
  19. package/dist/api/oauth/index.d.ts +287 -0
  20. package/dist/api/oauth/index.d.ts.map +1 -0
  21. package/dist/api/oauth/index.js +578 -0
  22. package/dist/api/oauth/index.js.map +1 -0
  23. package/dist/api/organizations/index.d.ts.map +1 -1
  24. package/dist/api/parameters/index.d.ts +2 -2
  25. package/dist/api/parameters/index.d.ts.map +1 -1
  26. package/dist/api/parameters/index.js +2 -2
  27. package/dist/api/parameters/index.js.map +1 -1
  28. package/dist/api/payments/index.d.ts +2 -0
  29. package/dist/api/payments/index.d.ts.map +1 -1
  30. package/dist/api/payments/index.js +5 -4
  31. package/dist/api/payments/index.js.map +1 -1
  32. package/dist/api/subscriptions/index.d.ts.map +1 -1
  33. package/dist/api/users/index.browser.js +8 -0
  34. package/dist/api/users/index.browser.js.map +1 -1
  35. package/dist/api/users/index.d.ts +286 -5039
  36. package/dist/api/users/index.d.ts.map +1 -1
  37. package/dist/api/users/index.js +59 -8
  38. package/dist/api/users/index.js.map +1 -1
  39. package/dist/api/verifications/index.d.ts +2 -0
  40. package/dist/api/verifications/index.d.ts.map +1 -1
  41. package/dist/api/verifications/index.js +4 -2
  42. package/dist/api/verifications/index.js.map +1 -1
  43. package/dist/batch/index.d.ts +2 -0
  44. package/dist/batch/index.d.ts.map +1 -1
  45. package/dist/batch/index.js +3 -1
  46. package/dist/batch/index.js.map +1 -1
  47. package/dist/bucket/index.d.ts +5 -0
  48. package/dist/bucket/index.d.ts.map +1 -1
  49. package/dist/bucket/index.js +9 -5
  50. package/dist/bucket/index.js.map +1 -1
  51. package/dist/bucket/index.workerd.js +5 -3
  52. package/dist/bucket/index.workerd.js.map +1 -1
  53. package/dist/cli/core/index.d.ts +157 -18
  54. package/dist/cli/core/index.d.ts.map +1 -1
  55. package/dist/cli/core/index.js +309 -44
  56. package/dist/cli/core/index.js.map +1 -1
  57. package/dist/cli/devtools/index.d.ts.map +1 -1
  58. package/dist/cli/devtools/index.js +10 -6
  59. package/dist/cli/devtools/index.js.map +1 -1
  60. package/dist/cli/i18n/index.d.ts +136 -0
  61. package/dist/cli/i18n/index.d.ts.map +1 -0
  62. package/dist/cli/i18n/index.js +245 -0
  63. package/dist/cli/i18n/index.js.map +1 -0
  64. package/dist/cli/platform/index.d.ts +39 -1
  65. package/dist/cli/platform/index.d.ts.map +1 -1
  66. package/dist/cli/platform/index.js +123 -5
  67. package/dist/cli/platform/index.js.map +1 -1
  68. package/dist/cli/vendor/index.d.ts +34 -9
  69. package/dist/cli/vendor/index.d.ts.map +1 -1
  70. package/dist/cli/vendor/index.js +55 -28
  71. package/dist/cli/vendor/index.js.map +1 -1
  72. package/dist/core/index.d.ts +0 -5
  73. package/dist/core/index.d.ts.map +1 -1
  74. package/dist/core/index.js +0 -22
  75. package/dist/core/index.js.map +1 -1
  76. package/dist/crypto/index.browser.js +73 -0
  77. package/dist/crypto/index.browser.js.map +1 -1
  78. package/dist/crypto/index.d.ts +10 -0
  79. package/dist/crypto/index.d.ts.map +1 -1
  80. package/dist/crypto/index.js +60 -0
  81. package/dist/crypto/index.js.map +1 -1
  82. package/dist/mcp/index.d.ts +40 -0
  83. package/dist/mcp/index.d.ts.map +1 -1
  84. package/dist/mcp/index.js +33 -2
  85. package/dist/mcp/index.js.map +1 -1
  86. package/dist/orm/core/index.bun.js +1254 -1070
  87. package/dist/orm/core/index.bun.js.map +1 -1
  88. package/dist/orm/core/index.d.ts +1494 -6228
  89. package/dist/orm/core/index.d.ts.map +1 -1
  90. package/dist/orm/core/index.js +2174 -2011
  91. package/dist/orm/core/index.js.map +1 -1
  92. package/dist/orm/postgres/index.bun.js +13 -20
  93. package/dist/orm/postgres/index.bun.js.map +1 -1
  94. package/dist/react/form/index.d.ts +0 -28
  95. package/dist/react/form/index.d.ts.map +1 -1
  96. package/dist/react/form/index.js +18 -4
  97. package/dist/react/form/index.js.map +1 -1
  98. package/dist/react/head/index.browser.js +3 -0
  99. package/dist/react/head/index.browser.js.map +1 -1
  100. package/dist/react/head/index.d.ts +13 -0
  101. package/dist/react/head/index.d.ts.map +1 -1
  102. package/dist/react/head/index.js +3 -0
  103. package/dist/react/head/index.js.map +1 -1
  104. package/dist/react/router/index.d.ts.map +1 -1
  105. package/dist/react/router/index.js +3 -0
  106. package/dist/react/router/index.js.map +1 -1
  107. package/dist/react/testing/index.js +3 -3
  108. package/dist/react/testing/index.js.map +1 -1
  109. package/dist/redis/index.bun.js +2 -6
  110. package/dist/redis/index.bun.js.map +1 -1
  111. package/dist/security/index.d.ts +14 -1
  112. package/dist/security/index.d.ts.map +1 -1
  113. package/dist/security/index.js +11 -7
  114. package/dist/security/index.js.map +1 -1
  115. package/dist/server/core/index.d.ts +2 -1
  116. package/dist/server/core/index.d.ts.map +1 -1
  117. package/dist/server/core/index.js +3 -3
  118. package/dist/server/core/index.js.map +1 -1
  119. package/dist/server/links/index.browser.js +18 -2
  120. package/dist/server/links/index.browser.js.map +1 -1
  121. package/dist/server/links/index.d.ts +1 -0
  122. package/dist/server/links/index.d.ts.map +1 -1
  123. package/dist/server/links/index.js +18 -2
  124. package/dist/server/links/index.js.map +1 -1
  125. package/dist/system/index.d.ts +159 -128
  126. package/dist/system/index.d.ts.map +1 -1
  127. package/dist/system/index.js +249 -181
  128. package/dist/system/index.js.map +1 -1
  129. package/package.json +36 -15
  130. package/src/api/files/__tests__/FileAccessProvider.spec.ts +87 -0
  131. package/src/api/files/__tests__/FileController.spec.ts +4 -0
  132. package/src/api/files/controllers/FileController.ts +14 -4
  133. package/src/api/files/entities/files.ts +25 -0
  134. package/src/api/files/index.ts +9 -1
  135. package/src/api/files/providers/FileAccessProvider.ts +52 -0
  136. package/src/api/files/services/FileService.ts +2 -0
  137. package/src/api/jobs/providers/JobProvider.ts +4 -2
  138. package/src/api/keys/controllers/ApiKeyController.ts +1 -0
  139. package/src/api/keys/schemas/listApiKeyResponseSchema.ts +1 -0
  140. package/src/api/oauth/__tests__/OAuthClientService.spec.ts +123 -0
  141. package/src/api/oauth/__tests__/OAuthController.spec.ts +233 -0
  142. package/src/api/oauth/controllers/OAuthController.ts +275 -0
  143. package/src/api/oauth/entities/oauthClientEntity.ts +31 -0
  144. package/src/api/oauth/helpers/consentPage.ts +65 -0
  145. package/src/api/oauth/helpers/oauthMetadata.ts +29 -0
  146. package/src/api/oauth/index.ts +38 -0
  147. package/src/api/oauth/schemas/authorizeDecisionBodySchema.ts +18 -0
  148. package/src/api/oauth/schemas/authorizeQuerySchema.ts +15 -0
  149. package/src/api/oauth/schemas/registerClientBodySchema.ts +16 -0
  150. package/src/api/oauth/schemas/tokenRequestBodySchema.ts +16 -0
  151. package/src/api/oauth/services/OAuthClientService.ts +267 -0
  152. package/src/api/parameters/services/ParameterProvider.ts +2 -2
  153. package/src/api/payments/providers/MemoryPaymentProvider.ts +6 -4
  154. package/src/api/users/__tests__/ApiKeys.spec.ts +30 -0
  155. package/src/api/users/__tests__/realmOauth.spec.ts +52 -0
  156. package/src/api/users/atoms/realmAuthSettingsAtom.ts +7 -0
  157. package/src/api/users/entities/sessions.ts +8 -0
  158. package/src/api/users/primitives/$realm.ts +83 -2
  159. package/src/api/users/services/CredentialService.ts +1 -2
  160. package/src/api/users/services/RegistrationService.ts +8 -7
  161. package/src/api/users/services/SessionService.ts +2 -0
  162. package/src/api/verifications/services/VerificationService.ts +4 -2
  163. package/src/batch/providers/BatchProvider.ts +3 -1
  164. package/src/bucket/providers/CloudflareR2Provider.ts +3 -1
  165. package/src/bucket/providers/LocalFileStorageProvider.ts +3 -2
  166. package/src/bucket/providers/MemoryFileStorageProvider.ts +3 -2
  167. package/src/bucket/providers/NodeS3BucketProvider.ts +3 -1
  168. package/src/cli/core/__tests__/BuildDockerTask.spec.ts +306 -0
  169. package/src/cli/core/__tests__/init.spec.ts +28 -9
  170. package/src/cli/core/atoms/buildOptions.ts +45 -0
  171. package/src/cli/core/commands/build.ts +27 -0
  172. package/src/cli/core/commands/db.ts +4 -1
  173. package/src/cli/core/commands/init.ts +0 -3
  174. package/src/cli/core/commands/lint.ts +4 -8
  175. package/src/cli/core/commands/test.ts +21 -10
  176. package/src/cli/core/commands/typecheck.ts +4 -10
  177. package/src/cli/core/commands/verify.ts +4 -3
  178. package/src/cli/core/services/AlephaCliUtils.ts +57 -1
  179. package/src/cli/core/services/PackageManagerUtils.ts +8 -24
  180. package/src/cli/core/services/ProjectScaffolder.ts +41 -5
  181. package/src/cli/core/tasks/BuildDockerTask.ts +191 -14
  182. package/src/cli/core/templates/agentMd.ts +7 -0
  183. package/src/cli/core/templates/alephaConfigTs.ts +14 -0
  184. package/src/cli/core/templates/dummySpecTs.ts +15 -3
  185. package/src/cli/core/templates/vscodeSettingsJson.ts +21 -0
  186. package/src/cli/devtools/index.ts +10 -6
  187. package/src/cli/i18n/__tests__/I18nCheckService.spec.ts +128 -0
  188. package/src/cli/i18n/atoms/i18nOptions.ts +51 -0
  189. package/src/cli/i18n/commands/I18nCommand.ts +81 -0
  190. package/src/cli/i18n/index.ts +52 -0
  191. package/src/cli/i18n/services/I18nCheckService.ts +144 -0
  192. package/src/cli/platform/adapters/CloudflareAdapter.ts +123 -31
  193. package/src/cli/platform/commands/SecretsCommand.ts +8 -4
  194. package/src/cli/platform/schemas/cloudflare.ts +24 -0
  195. package/src/cli/platform/services/CloudflareApi.ts +44 -0
  196. package/src/cli/vendor/__tests__/VendorService.spec.ts +32 -14
  197. package/src/cli/vendor/atoms/vendorOptions.ts +11 -1
  198. package/src/cli/vendor/commands/VendorCommand.ts +15 -3
  199. package/src/cli/vendor/services/VendorService.ts +55 -19
  200. package/src/core/index.ts +0 -32
  201. package/src/core/interfaces/Run.ts +0 -5
  202. package/src/crypto/__tests__/BrowserCryptoProvider.browser.spec.ts +58 -0
  203. package/src/crypto/providers/BrowserCryptoProvider.ts +115 -0
  204. package/src/crypto/providers/CryptoProvider.ts +99 -0
  205. package/src/mcp/__tests__/StreamableHttpMcpTransport.spec.ts +117 -0
  206. package/src/mcp/transports/StreamableHttpMcpTransport.ts +48 -0
  207. package/src/orm/__tests__/$sequence.spec.ts +87 -2
  208. package/src/orm/core/entities/alephaSequences.ts +42 -0
  209. package/src/orm/core/index.bun.ts +21 -20
  210. package/src/orm/core/index.shared-server.ts +2 -0
  211. package/src/orm/core/index.ts +2 -0
  212. package/src/orm/core/primitives/$sequence.ts +68 -27
  213. package/src/orm/core/providers/SequenceProvider.ts +103 -0
  214. package/src/orm/core/providers/drivers/CloudflareD1Provider.ts +7 -2
  215. package/src/orm/core/services/Repository.ts +22 -1
  216. package/src/orm/postgres/index.bun.ts +5 -12
  217. package/src/react/form/__tests__/useForm.browser.spec.tsx +434 -0
  218. package/src/react/form/hooks/useForm.ts +32 -5
  219. package/src/react/head/interfaces/Head.ts +13 -0
  220. package/src/react/head/providers/BrowserHeadProvider.ts +9 -0
  221. package/src/react/router/providers/ReactServerTemplateProvider.ts +4 -0
  222. package/src/redis/index.bun.ts +2 -6
  223. package/src/security/primitives/$issuer.ts +14 -0
  224. package/src/security/providers/ServerSecurityProvider.ts +20 -19
  225. package/src/server/core/__tests__/BunHttpServerProvider.bun.spec.ts +6 -6
  226. package/src/server/core/providers/ServerRouterProvider.ts +5 -2
  227. package/src/server/links/services/BatchCollector.ts +36 -2
  228. package/src/system/__tests__/BunShellProvider.bun.spec.ts +74 -0
  229. package/src/system/index.ts +13 -4
  230. package/src/system/providers/BunShellProvider.ts +81 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../src/api/files/schemas/storageStatsSchema.ts","../../../src/api/files/entities/files.ts","../../../src/api/files/services/FileService.ts","../../../src/api/files/controllers/AdminFileStatsController.ts","../../../src/api/files/schemas/fileQuerySchema.ts","../../../src/api/files/schemas/fileResourceSchema.ts","../../../src/api/files/controllers/FileController.ts","../../../src/api/files/jobs/FileJobs.ts","../../../src/api/files/index.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const bucketStatsSchema = t.object({\n bucket: t.string(),\n totalSize: t.number(),\n fileCount: t.number(),\n});\n\nexport const mimeTypeStatsSchema = t.object({\n mimeType: t.string(),\n fileCount: t.number(),\n});\n\nexport const storageStatsSchema = t.object({\n totalSize: t.number(),\n totalFiles: t.number(),\n byBucket: t.array(bucketStatsSchema),\n byMimeType: t.array(mimeTypeStatsSchema),\n});\n\nexport type BucketStats = Static<typeof bucketStatsSchema>;\nexport type MimeTypeStats = Static<typeof mimeTypeStatsSchema>;\nexport type StorageStats = Static<typeof storageStatsSchema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const files = $entity({\n name: \"files\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n blobId: t.text(),\n creator: t.optional(t.uuid()),\n creatorRealm: t.optional(t.string()),\n creatorName: t.optional(t.string()),\n bucket: t.text(),\n expirationDate: t.optional(t.datetime()),\n name: t.text(),\n size: t.number(),\n mimeType: t.string(),\n tags: t.optional(t.array(t.text())),\n checksum: t.optional(t.string()),\n }),\n indexes: [\n \"expirationDate\",\n \"bucket\",\n \"creator\",\n \"createdAt\",\n \"mimeType\",\n {\n columns: [\"bucket\", \"createdAt\"],\n },\n ],\n});\n\nexport type FileEntity = Static<typeof files.schema>;\n","import { createHash } from \"node:crypto\";\nimport { $hook, $inject, Alepha, type FileLike } from \"alepha\";\nimport {\n $bucket,\n type BucketPrimitive,\n FileNotFoundError,\n} from \"alepha/bucket\";\nimport {\n type DateTime,\n DateTimeProvider,\n type DurationLike,\n} from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository, type Page } from \"alepha/orm\";\nimport type { UserAccountToken } from \"alepha/security\";\nimport type { Ok } from \"alepha/server\";\nimport { NotFoundError } from \"alepha/server\";\nimport { type FileEntity, files } from \"../entities/files.ts\";\nimport type { FileQuery } from \"../schemas/fileQuerySchema.ts\";\nimport type { FileResource } from \"../schemas/fileResourceSchema.ts\";\nimport type { StorageStats } from \"../schemas/storageStatsSchema.ts\";\n\nexport class FileService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly defaultBucket = $bucket({ name: \"default\" });\n public readonly fileRepository = $repository(files);\n\n protected onUploadFile = $hook({\n on: \"bucket:file:uploaded\",\n handler: async ({ file, bucket, options, id }) => {\n if (options.persist === false) {\n return;\n }\n\n const checksum = await this.calculateChecksum(file);\n\n await this.fileRepository.create({\n blobId: id,\n mimeType: file.type,\n name: file.name,\n size: file.size,\n creator: options.user?.id,\n creatorRealm: options.user?.realm,\n expirationDate: this.getExpirationDate(options.ttl),\n bucket: bucket.name,\n checksum,\n });\n },\n });\n\n protected onDeleteBucketFile = $hook({\n on: \"bucket:file:deleted\",\n handler: async ({ bucket, id }) => {\n await this.fileRepository.deleteMany({\n blobId: { eq: id },\n bucket: { eq: bucket.name },\n });\n },\n });\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Calculates SHA-256 checksum of a file.\n *\n * @param file - The file to calculate checksum for\n * @returns Hexadecimal string representation of the SHA-256 hash\n * @protected\n */\n protected async calculateChecksum(file: FileLike): Promise<string> {\n const buffer = await file.arrayBuffer();\n const hash = createHash(\"sha256\");\n hash.update(Buffer.from(buffer));\n return hash.digest(\"hex\");\n }\n\n /**\n * Gets a bucket primitive by name.\n *\n * @param bucketName - The name of the bucket to retrieve (defaults to \"default\")\n * @returns The bucket primitive\n * @throws {NotFoundError} If the bucket is not found\n */\n public bucket(bucketName: string = this.defaultBucket.name): BucketPrimitive {\n const bucket = this.alepha\n .primitives($bucket)\n .find((it) => it.name === bucketName);\n\n if (!bucket) {\n throw new NotFoundError(`Bucket '${bucketName}' not found.`);\n }\n\n return bucket;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Finds files matching the given query criteria with pagination support.\n * Supports filtering by bucket, tags, name, mimeType, creator, and date range.\n *\n * @param q - Query parameters including bucket, tags, name, mimeType, creator, date range, pagination, and sorting\n * @returns Paginated list of file entities\n */\n public async findFiles(q: FileQuery = {}): Promise<Page<FileEntity>> {\n q.sort ??= \"-createdAt\";\n\n const where = this.fileRepository.createQueryWhere();\n\n if (q.bucket) {\n where.bucket = { eq: q.bucket };\n }\n\n if (q.tags) {\n where.tags = { arrayContains: q.tags };\n }\n\n if (q.name) {\n where.name = { ilike: `%${q.name}%` };\n }\n\n if (q.mimeType) {\n where.mimeType = { eq: q.mimeType };\n }\n\n if (q.creator) {\n where.creator = { eq: q.creator };\n }\n\n if (q.createdAfter && q.createdBefore) {\n where.createdAt = {\n gte: q.createdAfter,\n lte: q.createdBefore,\n };\n } else if (q.createdAfter) {\n where.createdAt = { gte: q.createdAfter };\n } else if (q.createdBefore) {\n where.createdAt = { lte: q.createdBefore };\n }\n\n return await this.fileRepository\n .paginate(q, { where }, { count: true })\n .then((page) => {\n return {\n ...page,\n content: page.content.map((it) => this.entityToResource(it)),\n };\n });\n }\n\n /**\n * Finds files that have expired based on their expiration date.\n * Limited to 1000 files per call to prevent memory issues.\n *\n * @returns Array of expired file entities\n */\n public async findExpiredFiles(): Promise<FileEntity[]> {\n return await this.fileRepository.findMany({\n limit: 1000,\n where: {\n expirationDate: { lte: this.dateTimeProvider.nowISOString() },\n },\n });\n }\n\n /**\n * Calculates an expiration date based on a TTL (time to live) duration.\n *\n * @param ttl - Duration like \"1 day\", \"2 hours\", etc.\n * @returns DateTime representation of the expiration date, or undefined if no TTL provided\n * @protected\n */\n protected getExpirationDate(ttl?: DurationLike): string | undefined {\n return ttl\n ? this.dateTimeProvider\n .now()\n .add(this.dateTimeProvider.duration(ttl))\n .toISOString()\n : undefined;\n }\n\n /**\n * Uploads a file to a bucket and creates a database record with metadata.\n * Automatically calculates and stores the file checksum (SHA-256).\n *\n * @param file - The file to upload\n * @param options - Upload options including bucket, expiration, user, and tags\n * @param options.bucket - Target bucket name (defaults to \"default\")\n * @param options.expirationDate - When the file should expire\n * @param options.user - User performing the upload (for audit trail)\n * @param options.tags - Tags to associate with the file\n * @returns The created file entity with all metadata\n * @throws {NotFoundError} If the specified bucket doesn't exist\n */\n public async uploadFile(\n file: FileLike,\n options: {\n expirationDate?: string | DateTime;\n bucket?: string;\n user?: UserAccountToken;\n tags?: string[];\n } = {},\n ): Promise<FileEntity> {\n const bucket = this.bucket(options.bucket);\n\n const checksum = await this.calculateChecksum(file);\n const blobId = await bucket.upload(file, { persist: false });\n\n let expirationDate: string | undefined;\n if (options.expirationDate) {\n expirationDate = this.dateTimeProvider\n .of(options.expirationDate)\n .toISOString();\n } else if (bucket.options.ttl) {\n expirationDate = this.getExpirationDate(bucket.options.ttl);\n }\n\n return await this.fileRepository.create({\n blobId: blobId,\n mimeType: file.type,\n name: file.name,\n size: file.size,\n creator: options.user?.id,\n creatorRealm: options.user?.realm,\n creatorName: options.user?.name,\n expirationDate,\n bucket: bucket.name,\n tags: options.tags,\n checksum,\n });\n }\n\n /**\n * Streams a file from storage by its database ID.\n *\n * @param id - The database ID (UUID) of the file to stream\n * @returns The file object ready for streaming/downloading\n * @throws {NotFoundError} If the file doesn't exist in the database\n * @throws {FileNotFoundError} If the file exists in database but not in storage\n */\n public async streamFile(id: string): Promise<FileLike> {\n const entity = await this.getFileById(id);\n const bucket = this.bucket(entity.bucket);\n\n return await bucket.download(entity.blobId);\n }\n\n /**\n * Updates file metadata (name, tags, expiration date).\n * Does not modify the actual file content in storage.\n *\n * @param id - The database ID (UUID) of the file to update\n * @param data - Partial file data to update\n * @param data.name - New file name\n * @param data.tags - New tags array\n * @param data.expirationDate - New expiration date\n * @returns The updated file entity\n * @throws {NotFoundError} If the file doesn't exist in the database\n */\n public async updateFile(\n id: string,\n data: {\n name?: string;\n tags?: string[];\n expirationDate?: DateTime | string;\n },\n ): Promise<FileEntity> {\n const file = await this.getFileById(id);\n\n const updateData: Partial<FileEntity> = {};\n\n if (data.name !== undefined) {\n updateData.name = data.name;\n }\n\n if (data.tags !== undefined) {\n updateData.tags = data.tags;\n }\n\n if (data.expirationDate !== undefined) {\n updateData.expirationDate = this.dateTimeProvider\n .of(data.expirationDate)\n .toISOString();\n }\n\n return await this.fileRepository.updateById(file.id, updateData);\n }\n\n /**\n * Deletes a file from both storage and database.\n * Handles cases where file is already deleted from storage gracefully.\n * Always ensures database record is removed even if storage deletion fails.\n *\n * @param id - The database ID (UUID) of the file to delete\n * @returns Success response with the deleted file ID\n * @throws {NotFoundError} If the file doesn't exist in the database\n */\n public async deleteFile(id: string): Promise<Ok> {\n const file = await this.getFileById(id);\n const bucket = this.bucket(file.bucket);\n\n // Always delete the database record\n await this.fileRepository.deleteById(file.id);\n\n try {\n await bucket.delete(file.blobId, true);\n } catch (e) {\n if (e instanceof FileNotFoundError) {\n // File is already deleted in the bucket, this is okay\n this.log.debug(\n `File ${file.blobId} not found in bucket ${bucket.name}, cleaning up database record`,\n );\n } else {\n // Other errors (permission, network, etc.) - log but continue to clean up database\n this.log.warn(\n `Failed to delete file ${file.blobId} from bucket ${bucket.name}`,\n e,\n );\n }\n }\n\n return { ok: true, id: String(file.id) };\n }\n\n /**\n * Delete many files in one round-trip per bucket. The database rows are\n * removed in a single `deleteMany`, and each affected bucket gets a single\n * `bucket.deleteMany` call (R2/S3 batch where supported).\n */\n public async deleteFiles(ids: string[]): Promise<string[]> {\n if (ids.length === 0) return [];\n\n const files = await this.fileRepository.findMany({\n where: { id: { inArray: ids } },\n columns: [\"id\", \"bucket\", \"blobId\"],\n });\n if (files.length === 0) return [];\n\n const dbDeleted = await this.fileRepository.deleteMany({\n id: { inArray: files.map((f) => f.id) },\n });\n\n const blobsByBucket = new Map<string, string[]>();\n for (const f of files) {\n const list = blobsByBucket.get(f.bucket) ?? [];\n list.push(f.blobId);\n blobsByBucket.set(f.bucket, list);\n }\n\n for (const [bucketName, blobIds] of blobsByBucket) {\n try {\n await this.bucket(bucketName).deleteMany(blobIds, true);\n } catch (e) {\n // DB rows already gone — log and continue. Orphaned blobs are\n // recoverable; orphaned DB rows would be worse.\n this.log.warn(\n `Failed to bulk-delete ${blobIds.length} files from bucket ${bucketName}`,\n e,\n );\n }\n }\n\n return dbDeleted.map(String);\n }\n\n /**\n * Retrieves a file entity by its ID.\n * If already an entity object, returns it as-is (convenience method).\n *\n * @param id - Either a UUID string or an existing FileEntity object\n * @returns The file entity\n * @throws {NotFoundError} If the file doesn't exist in the database\n */\n public async getFileById(id: string | FileEntity): Promise<FileEntity> {\n if (typeof id === \"object\") {\n return id;\n }\n\n return await this.fileRepository.getById(id);\n }\n\n /**\n * Gets storage statistics including total size, file count, and breakdowns by bucket and MIME type.\n *\n * @returns Storage statistics with aggregated data\n */\n public async getStorageStats(): Promise<StorageStats> {\n const allFiles = await this.fileRepository.findMany({});\n\n const totalSize = allFiles.reduce((sum, file) => sum + file.size, 0);\n const totalFiles = allFiles.length;\n\n // Group by bucket\n const bucketMap = new Map<\n string,\n { totalSize: number; fileCount: number }\n >();\n for (const file of allFiles) {\n const existing = bucketMap.get(file.bucket) || {\n totalSize: 0,\n fileCount: 0,\n };\n existing.totalSize += file.size;\n existing.fileCount += 1;\n bucketMap.set(file.bucket, existing);\n }\n\n // Group by MIME type\n const mimeTypeMap = new Map<string, number>();\n for (const file of allFiles) {\n const existing = mimeTypeMap.get(file.mimeType) || 0;\n mimeTypeMap.set(file.mimeType, existing + 1);\n }\n\n return {\n totalSize,\n totalFiles,\n byBucket: Array.from(bucketMap.entries()).map(([bucket, stats]) => ({\n bucket,\n totalSize: stats.totalSize,\n fileCount: stats.fileCount,\n })),\n byMimeType: Array.from(mimeTypeMap.entries()).map(\n ([mimeType, fileCount]) => ({\n mimeType,\n fileCount,\n }),\n ),\n };\n }\n\n /**\n * Converts a file entity to a file resource (API response format).\n * Currently a pass-through, but allows for future transformation logic.\n *\n * @param entity - The file entity to convert\n * @returns The file resource for API responses\n */\n public entityToResource(entity: FileEntity): FileResource {\n return entity;\n }\n}\n","import { $inject } from \"alepha\";\nimport { $secure } from \"alepha/security\";\nimport { $action } from \"alepha/server\";\nimport { storageStatsSchema } from \"../schemas/storageStatsSchema.ts\";\nimport { FileService } from \"../services/FileService.ts\";\n\n/**\n * REST API controller for storage analytics and statistics.\n * Provides endpoints for viewing storage usage metrics.\n */\nexport class AdminFileStatsController {\n protected readonly url = \"/files/stats\";\n protected readonly group = \"admin:files\";\n protected readonly fileService = $inject(FileService);\n\n /**\n * GET /files/stats - Gets storage statistics.\n * Returns aggregated data including total size, file count,\n * and breakdowns by bucket and MIME type.\n */\n public readonly getFileStats = $action({\n path: this.url,\n group: this.group,\n use: [$secure({ permissions: [\"admin:file:read\"] })],\n description: \"Get storage statistics\",\n schema: {\n response: storageStatsSchema,\n },\n handler: () => this.fileService.getStorageStats(),\n });\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const fileQuerySchema = t.extend(pageQuerySchema, {\n bucket: t.optional(t.string()),\n tags: t.optional(t.array(t.string())),\n name: t.optional(t.string()),\n mimeType: t.optional(t.string()),\n creator: t.optional(t.uuid()),\n createdAfter: t.optional(t.datetime()),\n createdBefore: t.optional(t.datetime()),\n});\n\nexport type FileQuery = Static<typeof fileQuerySchema>;\n","import { type Static, t } from \"alepha\";\nimport { files } from \"../entities/files.ts\";\n\nexport const fileResourceSchema = t.extend(\n files.schema,\n {},\n {\n title: \"FileResource\",\n description: \"A file resource representing a file stored in the system.\",\n },\n);\n\nexport type FileResource = Static<typeof fileResourceSchema>;\n","import { $inject, t } from \"alepha\";\nimport { $secure } from \"alepha/security\";\nimport { $action, okSchema } from \"alepha/server\";\nimport { $etag } from \"alepha/server/etag\";\nimport { fileQuerySchema } from \"../schemas/fileQuerySchema.ts\";\nimport { fileResourceSchema } from \"../schemas/fileResourceSchema.ts\";\nimport { FileService } from \"../services/FileService.ts\";\n\n/**\n * REST API controller for file management operations.\n * Provides endpoints for uploading, downloading, listing, and deleting files.\n */\nexport class FileController {\n protected readonly url = \"/files\";\n protected readonly group = \"files\";\n protected readonly fileService = $inject(FileService);\n\n /**\n * GET /files - Lists files with optional filtering and pagination.\n * Supports filtering by bucket and tags.\n */\n public readonly findFiles = $action({\n path: this.url,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:read\"] })],\n description: \"List files with filtering and pagination\",\n schema: {\n query: fileQuerySchema,\n response: t.page(fileResourceSchema),\n },\n handler: ({ query }) => this.fileService.findFiles(query),\n });\n\n /**\n * DELETE /files/:id - Deletes a file from both storage and database.\n * Removes the file from the bucket and cleans up the database record.\n */\n public readonly deleteFile = $action({\n method: \"DELETE\",\n path: `${this.url}/:id`,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:delete\"] })],\n description: \"Delete a file\",\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n response: okSchema,\n },\n handler: ({ params }) => this.fileService.deleteFile(params.id),\n });\n\n /**\n * POST /files/delete - Delete many files in one request, batching the\n * underlying bucket calls per bucket (R2/S3 batch where supported).\n */\n public readonly deleteFiles = $action({\n method: \"POST\",\n path: `${this.url}/delete`,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:delete\"] })],\n description: \"Delete many files\",\n schema: {\n body: t.object({\n ids: t.array(t.uuid(), { minItems: 1, maxItems: 1000 }),\n }),\n response: t.object({\n deleted: t.array(t.string()),\n }),\n },\n handler: async ({ body }) => {\n const deleted = await this.fileService.deleteFiles(body.ids);\n return { deleted };\n },\n });\n\n /**\n * POST /files - Uploads a new file to storage.\n * Creates a database record with metadata and calculates checksum.\n * Optionally specify bucket and expiration date.\n */\n public readonly uploadFile = $action({\n path: this.url,\n group: this.group,\n use: [$secure({ permissions: [\"file:create\"] })],\n description: \"Upload a new file\",\n schema: {\n body: t.object({\n file: t.file(),\n }),\n query: t.object({\n expirationDate: t.optional(t.datetime()),\n bucket: t.optional(t.string()),\n }),\n response: fileResourceSchema,\n },\n handler: async ({ body, user, query }) =>\n this.fileService.uploadFile(body.file, {\n user,\n ...query,\n }),\n });\n\n /**\n * PATCH /files/:id - Updates file metadata.\n * Allows updating name, tags, and expiration date without modifying file content.\n */\n public readonly updateFile = $action({\n method: \"PATCH\",\n path: `${this.url}/:id`,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:update\"] })],\n description: \"Update file metadata\",\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n body: t.object({\n name: t.optional(t.string()),\n tags: t.optional(t.array(t.string())),\n expirationDate: t.optional(t.datetime()),\n }),\n response: fileResourceSchema,\n },\n handler: ({ params, body }) => this.fileService.updateFile(params.id, body),\n });\n\n /**\n * GET /files/:id - Streams/downloads a file by its ID.\n * Returns the file content with appropriate Content-Type header.\n * Cached with ETag support for 1 year (immutable).\n */\n public readonly streamFile = $action({\n path: `${this.url}/:id`,\n group: this.group,\n description: \"Download a file\",\n use: [\n $secure({ permissions: [\"file:read\"] }),\n $etag({\n control: {\n public: true,\n maxAge: [1, \"year\"],\n immutable: true,\n },\n }),\n ],\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n response: t.file(),\n },\n handler: async ({ params }) => {\n return await this.fileService.streamFile(params.id);\n },\n });\n}\n","import { $inject } from \"alepha\";\nimport { $scheduler } from \"alepha/scheduler\";\nimport { FileService } from \"../services/FileService.ts\";\n\nexport class FileJobs {\n protected readonly fileService = $inject(FileService);\n\n public readonly purgeFiles = $scheduler({\n name: \"api:files:purgeFiles\",\n description: \"Purge files that are marked for deletion\",\n cron: \"0 * * * *\", // Hourly at minute 0\n handler: async () => {\n const files = await this.fileService.findExpiredFiles();\n\n await Promise.all(\n files.map((file) => this.fileService.deleteFile(file.id)),\n );\n },\n });\n}\n","import { $module } from \"alepha\";\nimport { AlephaBucket } from \"alepha/bucket\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport type { UserAccountToken } from \"alepha/security\";\nimport { AlephaServerEtag } from \"alepha/server/etag\";\nimport { AdminFileStatsController } from \"./controllers/AdminFileStatsController.ts\";\nimport { FileController } from \"./controllers/FileController.ts\";\nimport { FileJobs } from \"./jobs/FileJobs.ts\";\nimport { FileService } from \"./services/FileService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/AdminFileStatsController.ts\";\nexport * from \"./controllers/FileController.ts\";\nexport * from \"./entities/files.ts\";\nexport * from \"./jobs/FileJobs.ts\";\nexport * from \"./schemas/storageStatsSchema.ts\";\nexport * from \"./services/FileService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/bucket\" {\n interface BucketFileOptions {\n /**\n * Time to live for the files in the bucket.\n */\n ttl?: DurationLike;\n\n /**\n * Tags for the bucket.\n */\n tags?: string[];\n\n /**\n * User performing the operation.\n */\n user?: UserAccountToken;\n\n /**\n * Whether to persist the file metadata in the database.\n *\n * @default true\n */\n persist?: boolean;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * File management endpoints.\n *\n * **Features:**\n * - Upload/download endpoints\n * - File metadata storage\n * - TTL-based expiration\n * - Storage statistics\n *\n * @module alepha.api.files\n */\nexport const AlephaApiFiles = $module({\n name: \"alepha.api.files\",\n services: [FileController, AdminFileStatsController, FileJobs, FileService],\n imports: [AlephaBucket, AlephaServerEtag],\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../src/api/files/schemas/storageStatsSchema.ts","../../../src/api/files/entities/files.ts","../../../src/api/files/services/FileService.ts","../../../src/api/files/controllers/AdminFileStatsController.ts","../../../src/api/files/providers/FileAccessProvider.ts","../../../src/api/files/schemas/fileQuerySchema.ts","../../../src/api/files/schemas/fileResourceSchema.ts","../../../src/api/files/controllers/FileController.ts","../../../src/api/files/jobs/FileJobs.ts","../../../src/api/files/index.ts"],"sourcesContent":["import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\n\nexport const bucketStatsSchema = t.object({\n bucket: t.string(),\n totalSize: t.number(),\n fileCount: t.number(),\n});\n\nexport const mimeTypeStatsSchema = t.object({\n mimeType: t.string(),\n fileCount: t.number(),\n});\n\nexport const storageStatsSchema = t.object({\n totalSize: t.number(),\n totalFiles: t.number(),\n byBucket: t.array(bucketStatsSchema),\n byMimeType: t.array(mimeTypeStatsSchema),\n});\n\nexport type BucketStats = Static<typeof bucketStatsSchema>;\nexport type MimeTypeStats = Static<typeof mimeTypeStatsSchema>;\nexport type StorageStats = Static<typeof storageStatsSchema>;\n","import { type Static, t } from \"alepha\";\nimport { $entity, db } from \"alepha/orm\";\n\nexport const files = $entity({\n name: \"files\",\n schema: t.object({\n id: db.primaryKey(t.uuid()),\n version: db.version(),\n createdAt: db.createdAt(),\n updatedAt: db.updatedAt(),\n organizationId: db.organization(),\n blobId: t.text(),\n creator: t.optional(t.uuid()),\n creatorRealm: t.optional(t.string()),\n creatorName: t.optional(t.string()),\n bucket: t.text(),\n expirationDate: t.optional(t.datetime()),\n /**\n * Display name. Mutable via `FileService.updateFile` — can be renamed\n * by callers (e.g. an Archive UI letting users rename uploaded blobs).\n * Initialized to the uploader's filename at upload time. Use\n * `originalName` if you need the as-uploaded filename after a rename.\n */\n name: t.text(),\n /**\n * Immutable record of the uploader's filename at upload time. Set once\n * by `FileService.uploadFile` and the `bucket:file:uploaded` hook;\n * `FileService.updateFile` never touches it. Useful for download\n * headers (Content-Disposition), audit trails, and any UI that wants\n * to show \"originally uploaded as X\" alongside a renamed file.\n */\n originalName: t.optional(t.string()),\n size: t.number(),\n mimeType: t.string(),\n /**\n * Free-form taxonomy. Normalized server-side (trim/lowercase/dedupe is\n * caller's responsibility for now). Use with `FileQuery.tags` to\n * filter via array-contains.\n */\n tags: t.optional(t.array(t.text())),\n /**\n * SHA-256 hex digest of the file content (64 lowercase hex chars).\n * Computed at upload time by `FileService.calculateChecksum`. Stable\n * — never recomputed after upload. Use for integrity verification,\n * content-based dedup, or downstream virus-scan correlation.\n */\n checksum: t.optional(t.string()),\n }),\n indexes: [\n \"expirationDate\",\n \"bucket\",\n \"creator\",\n \"createdAt\",\n \"mimeType\",\n {\n columns: [\"bucket\", \"createdAt\"],\n },\n ],\n});\n\nexport type FileEntity = Static<typeof files.schema>;\n","import { createHash } from \"node:crypto\";\nimport { $hook, $inject, Alepha, type FileLike } from \"alepha\";\nimport {\n $bucket,\n type BucketPrimitive,\n FileNotFoundError,\n} from \"alepha/bucket\";\nimport {\n type DateTime,\n DateTimeProvider,\n type DurationLike,\n} from \"alepha/datetime\";\nimport { $logger } from \"alepha/logger\";\nimport { $repository, type Page } from \"alepha/orm\";\nimport type { UserAccountToken } from \"alepha/security\";\nimport type { Ok } from \"alepha/server\";\nimport { NotFoundError } from \"alepha/server\";\nimport { type FileEntity, files } from \"../entities/files.ts\";\nimport type { FileQuery } from \"../schemas/fileQuerySchema.ts\";\nimport type { FileResource } from \"../schemas/fileResourceSchema.ts\";\nimport type { StorageStats } from \"../schemas/storageStatsSchema.ts\";\n\nexport class FileService {\n protected readonly alepha = $inject(Alepha);\n protected readonly log = $logger();\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n protected readonly defaultBucket = $bucket({ name: \"default\" });\n public readonly fileRepository = $repository(files);\n\n protected onUploadFile = $hook({\n on: \"bucket:file:uploaded\",\n handler: async ({ file, bucket, options, id }) => {\n if (options.persist === false) {\n return;\n }\n\n const checksum = await this.calculateChecksum(file);\n\n await this.fileRepository.create({\n blobId: id,\n mimeType: file.type,\n name: file.name,\n originalName: file.name,\n size: file.size,\n creator: options.user?.id,\n creatorRealm: options.user?.realm,\n expirationDate: this.getExpirationDate(options.ttl),\n bucket: bucket.name,\n checksum,\n });\n },\n });\n\n protected onDeleteBucketFile = $hook({\n on: \"bucket:file:deleted\",\n handler: async ({ bucket, id }) => {\n await this.fileRepository.deleteMany({\n blobId: { eq: id },\n bucket: { eq: bucket.name },\n });\n },\n });\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Calculates SHA-256 checksum of a file.\n *\n * @param file - The file to calculate checksum for\n * @returns Hexadecimal string representation of the SHA-256 hash\n * @protected\n */\n protected async calculateChecksum(file: FileLike): Promise<string> {\n const buffer = await file.arrayBuffer();\n const hash = createHash(\"sha256\");\n hash.update(Buffer.from(buffer));\n return hash.digest(\"hex\");\n }\n\n /**\n * Gets a bucket primitive by name.\n *\n * @param bucketName - The name of the bucket to retrieve (defaults to \"default\")\n * @returns The bucket primitive\n * @throws {NotFoundError} If the bucket is not found\n */\n public bucket(bucketName: string = this.defaultBucket.name): BucketPrimitive {\n const bucket = this.alepha\n .primitives($bucket)\n .find((it) => it.name === bucketName);\n\n if (!bucket) {\n throw new NotFoundError(`Bucket '${bucketName}' not found.`);\n }\n\n return bucket;\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n /**\n * Finds files matching the given query criteria with pagination support.\n * Supports filtering by bucket, tags, name, mimeType, creator, and date range.\n *\n * @param q - Query parameters including bucket, tags, name, mimeType, creator, date range, pagination, and sorting\n * @returns Paginated list of file entities\n */\n public async findFiles(q: FileQuery = {}): Promise<Page<FileEntity>> {\n q.sort ??= \"-createdAt\";\n\n const where = this.fileRepository.createQueryWhere();\n\n if (q.bucket) {\n where.bucket = { eq: q.bucket };\n }\n\n if (q.tags) {\n where.tags = { arrayContains: q.tags };\n }\n\n if (q.name) {\n where.name = { ilike: `%${q.name}%` };\n }\n\n if (q.mimeType) {\n where.mimeType = { eq: q.mimeType };\n }\n\n if (q.creator) {\n where.creator = { eq: q.creator };\n }\n\n if (q.createdAfter && q.createdBefore) {\n where.createdAt = {\n gte: q.createdAfter,\n lte: q.createdBefore,\n };\n } else if (q.createdAfter) {\n where.createdAt = { gte: q.createdAfter };\n } else if (q.createdBefore) {\n where.createdAt = { lte: q.createdBefore };\n }\n\n return await this.fileRepository\n .paginate(q, { where }, { count: true })\n .then((page) => {\n return {\n ...page,\n content: page.content.map((it) => this.entityToResource(it)),\n };\n });\n }\n\n /**\n * Finds files that have expired based on their expiration date.\n * Limited to 1000 files per call to prevent memory issues.\n *\n * @returns Array of expired file entities\n */\n public async findExpiredFiles(): Promise<FileEntity[]> {\n return await this.fileRepository.findMany({\n limit: 1000,\n where: {\n expirationDate: { lte: this.dateTimeProvider.nowISOString() },\n },\n });\n }\n\n /**\n * Calculates an expiration date based on a TTL (time to live) duration.\n *\n * @param ttl - Duration like \"1 day\", \"2 hours\", etc.\n * @returns DateTime representation of the expiration date, or undefined if no TTL provided\n * @protected\n */\n protected getExpirationDate(ttl?: DurationLike): string | undefined {\n return ttl\n ? this.dateTimeProvider\n .now()\n .add(this.dateTimeProvider.duration(ttl))\n .toISOString()\n : undefined;\n }\n\n /**\n * Uploads a file to a bucket and creates a database record with metadata.\n * Automatically calculates and stores the file checksum (SHA-256).\n *\n * @param file - The file to upload\n * @param options - Upload options including bucket, expiration, user, and tags\n * @param options.bucket - Target bucket name (defaults to \"default\")\n * @param options.expirationDate - When the file should expire\n * @param options.user - User performing the upload (for audit trail)\n * @param options.tags - Tags to associate with the file\n * @returns The created file entity with all metadata\n * @throws {NotFoundError} If the specified bucket doesn't exist\n */\n public async uploadFile(\n file: FileLike,\n options: {\n expirationDate?: string | DateTime;\n bucket?: string;\n user?: UserAccountToken;\n tags?: string[];\n } = {},\n ): Promise<FileEntity> {\n const bucket = this.bucket(options.bucket);\n\n const checksum = await this.calculateChecksum(file);\n const blobId = await bucket.upload(file, { persist: false });\n\n let expirationDate: string | undefined;\n if (options.expirationDate) {\n expirationDate = this.dateTimeProvider\n .of(options.expirationDate)\n .toISOString();\n } else if (bucket.options.ttl) {\n expirationDate = this.getExpirationDate(bucket.options.ttl);\n }\n\n return await this.fileRepository.create({\n blobId: blobId,\n mimeType: file.type,\n name: file.name,\n originalName: file.name,\n size: file.size,\n creator: options.user?.id,\n creatorRealm: options.user?.realm,\n creatorName: options.user?.name,\n expirationDate,\n bucket: bucket.name,\n tags: options.tags,\n checksum,\n });\n }\n\n /**\n * Streams a file from storage by its database ID.\n *\n * @param id - The database ID (UUID) of the file to stream\n * @returns The file object ready for streaming/downloading\n * @throws {NotFoundError} If the file doesn't exist in the database\n * @throws {FileNotFoundError} If the file exists in database but not in storage\n */\n public async streamFile(id: string): Promise<FileLike> {\n const entity = await this.getFileById(id);\n const bucket = this.bucket(entity.bucket);\n\n return await bucket.download(entity.blobId);\n }\n\n /**\n * Updates file metadata (name, tags, expiration date).\n * Does not modify the actual file content in storage.\n *\n * @param id - The database ID (UUID) of the file to update\n * @param data - Partial file data to update\n * @param data.name - New file name\n * @param data.tags - New tags array\n * @param data.expirationDate - New expiration date\n * @returns The updated file entity\n * @throws {NotFoundError} If the file doesn't exist in the database\n */\n public async updateFile(\n id: string,\n data: {\n name?: string;\n tags?: string[];\n expirationDate?: DateTime | string;\n },\n ): Promise<FileEntity> {\n const file = await this.getFileById(id);\n\n const updateData: Partial<FileEntity> = {};\n\n if (data.name !== undefined) {\n updateData.name = data.name;\n }\n\n if (data.tags !== undefined) {\n updateData.tags = data.tags;\n }\n\n if (data.expirationDate !== undefined) {\n updateData.expirationDate = this.dateTimeProvider\n .of(data.expirationDate)\n .toISOString();\n }\n\n return await this.fileRepository.updateById(file.id, updateData);\n }\n\n /**\n * Deletes a file from both storage and database.\n * Handles cases where file is already deleted from storage gracefully.\n * Always ensures database record is removed even if storage deletion fails.\n *\n * @param id - The database ID (UUID) of the file to delete\n * @returns Success response with the deleted file ID\n * @throws {NotFoundError} If the file doesn't exist in the database\n */\n public async deleteFile(id: string): Promise<Ok> {\n const file = await this.getFileById(id);\n const bucket = this.bucket(file.bucket);\n\n // Always delete the database record\n await this.fileRepository.deleteById(file.id);\n\n try {\n await bucket.delete(file.blobId, true);\n } catch (e) {\n if (e instanceof FileNotFoundError) {\n // File is already deleted in the bucket, this is okay\n this.log.debug(\n `File ${file.blobId} not found in bucket ${bucket.name}, cleaning up database record`,\n );\n } else {\n // Other errors (permission, network, etc.) - log but continue to clean up database\n this.log.warn(\n `Failed to delete file ${file.blobId} from bucket ${bucket.name}`,\n e,\n );\n }\n }\n\n return { ok: true, id: String(file.id) };\n }\n\n /**\n * Delete many files in one round-trip per bucket. The database rows are\n * removed in a single `deleteMany`, and each affected bucket gets a single\n * `bucket.deleteMany` call (R2/S3 batch where supported).\n */\n public async deleteFiles(ids: string[]): Promise<string[]> {\n if (ids.length === 0) return [];\n\n const files = await this.fileRepository.findMany({\n where: { id: { inArray: ids } },\n columns: [\"id\", \"bucket\", \"blobId\"],\n });\n if (files.length === 0) return [];\n\n const dbDeleted = await this.fileRepository.deleteMany({\n id: { inArray: files.map((f) => f.id) },\n });\n\n const blobsByBucket = new Map<string, string[]>();\n for (const f of files) {\n const list = blobsByBucket.get(f.bucket) ?? [];\n list.push(f.blobId);\n blobsByBucket.set(f.bucket, list);\n }\n\n for (const [bucketName, blobIds] of blobsByBucket) {\n try {\n await this.bucket(bucketName).deleteMany(blobIds, true);\n } catch (e) {\n // DB rows already gone — log and continue. Orphaned blobs are\n // recoverable; orphaned DB rows would be worse.\n this.log.warn(\n `Failed to bulk-delete ${blobIds.length} files from bucket ${bucketName}`,\n e,\n );\n }\n }\n\n return dbDeleted.map(String);\n }\n\n /**\n * Retrieves a file entity by its ID.\n * If already an entity object, returns it as-is (convenience method).\n *\n * @param id - Either a UUID string or an existing FileEntity object\n * @returns The file entity\n * @throws {NotFoundError} If the file doesn't exist in the database\n */\n public async getFileById(id: string | FileEntity): Promise<FileEntity> {\n if (typeof id === \"object\") {\n return id;\n }\n\n return await this.fileRepository.getById(id);\n }\n\n /**\n * Gets storage statistics including total size, file count, and breakdowns by bucket and MIME type.\n *\n * @returns Storage statistics with aggregated data\n */\n public async getStorageStats(): Promise<StorageStats> {\n const allFiles = await this.fileRepository.findMany({});\n\n const totalSize = allFiles.reduce((sum, file) => sum + file.size, 0);\n const totalFiles = allFiles.length;\n\n // Group by bucket\n const bucketMap = new Map<\n string,\n { totalSize: number; fileCount: number }\n >();\n for (const file of allFiles) {\n const existing = bucketMap.get(file.bucket) || {\n totalSize: 0,\n fileCount: 0,\n };\n existing.totalSize += file.size;\n existing.fileCount += 1;\n bucketMap.set(file.bucket, existing);\n }\n\n // Group by MIME type\n const mimeTypeMap = new Map<string, number>();\n for (const file of allFiles) {\n const existing = mimeTypeMap.get(file.mimeType) || 0;\n mimeTypeMap.set(file.mimeType, existing + 1);\n }\n\n return {\n totalSize,\n totalFiles,\n byBucket: Array.from(bucketMap.entries()).map(([bucket, stats]) => ({\n bucket,\n totalSize: stats.totalSize,\n fileCount: stats.fileCount,\n })),\n byMimeType: Array.from(mimeTypeMap.entries()).map(\n ([mimeType, fileCount]) => ({\n mimeType,\n fileCount,\n }),\n ),\n };\n }\n\n /**\n * Converts a file entity to a file resource (API response format).\n * Currently a pass-through, but allows for future transformation logic.\n *\n * @param entity - The file entity to convert\n * @returns The file resource for API responses\n */\n public entityToResource(entity: FileEntity): FileResource {\n return entity;\n }\n}\n","import { $inject } from \"alepha\";\nimport { $secure } from \"alepha/security\";\nimport { $action } from \"alepha/server\";\nimport { storageStatsSchema } from \"../schemas/storageStatsSchema.ts\";\nimport { FileService } from \"../services/FileService.ts\";\n\n/**\n * REST API controller for storage analytics and statistics.\n * Provides endpoints for viewing storage usage metrics.\n */\nexport class AdminFileStatsController {\n protected readonly url = \"/files/stats\";\n protected readonly group = \"admin:files\";\n protected readonly fileService = $inject(FileService);\n\n /**\n * GET /files/stats - Gets storage statistics.\n * Returns aggregated data including total size, file count,\n * and breakdowns by bucket and MIME type.\n */\n public readonly getFileStats = $action({\n path: this.url,\n group: this.group,\n use: [$secure({ permissions: [\"admin:file:read\"] })],\n description: \"Get storage statistics\",\n schema: {\n response: storageStatsSchema,\n },\n handler: () => this.fileService.getStorageStats(),\n });\n}\n","import type { UserAccountToken } from \"alepha/security\";\nimport { ForbiddenError } from \"alepha/server\";\nimport type { FileEntity } from \"../entities/files.ts\";\n\n/**\n * Authorization policy for file reads served through `FileController.streamFile`.\n *\n * Default: the caller must be the uploader (`file.creator === user.id`). Any\n * other access path — public buckets, shared attachments, avatars — must be\n * opted in by overriding this provider in the consuming app:\n *\n * ```ts\n * class MyAccess extends FileAccessProvider {\n * async assertReadable(file, user) {\n * if (file.bucket === \"avatars\") return; // public\n * if (file.bucket === \"campaign-icons\") return this.checkCampaignVisible(file, user);\n * return super.assertReadable(file, user);\n * }\n * }\n * Alepha.create().with({ provide: FileAccessProvider, use: MyAccess });\n * ```\n *\n * Why this exists: prior to introducing this gate, `streamFile` only required\n * the framework-wide `file:read` permission. The default `user` role grants\n * `*`, so every authenticated user could download any file by UUID — turning\n * the 128-bit id into the sole security boundary across tenants.\n */\nexport class FileAccessProvider {\n /**\n * Throws `ForbiddenError` when `user` may not read `file`. Override to\n * implement bucket-aware or relationship-aware policies. The default\n * implementation is strict: only the uploader passes.\n */\n async assertReadable(\n file: FileEntity,\n user: UserAccountToken | undefined,\n ): Promise<void> {\n if (!user) {\n throw new ForbiddenError(\"File access requires authentication\");\n }\n // Privileged identities (admin without narrow ownership scope) bypass\n // the per-file check — they need to be able to read any file via the\n // admin UI/inspector regardless of who uploaded it.\n if (user.ownership === false) {\n return;\n }\n if (file.creator && file.creator === user.id) {\n return;\n }\n throw new ForbiddenError(\"File access denied\");\n }\n}\n","import type { Static } from \"alepha\";\nimport { t } from \"alepha\";\nimport { pageQuerySchema } from \"alepha/orm\";\n\nexport const fileQuerySchema = t.extend(pageQuerySchema, {\n bucket: t.optional(t.string()),\n tags: t.optional(t.array(t.string())),\n name: t.optional(t.string()),\n mimeType: t.optional(t.string()),\n creator: t.optional(t.uuid()),\n createdAfter: t.optional(t.datetime()),\n createdBefore: t.optional(t.datetime()),\n});\n\nexport type FileQuery = Static<typeof fileQuerySchema>;\n","import { type Static, t } from \"alepha\";\nimport { files } from \"../entities/files.ts\";\n\nexport const fileResourceSchema = t.extend(\n files.schema,\n {},\n {\n title: \"FileResource\",\n description: \"A file resource representing a file stored in the system.\",\n },\n);\n\nexport type FileResource = Static<typeof fileResourceSchema>;\n","import { $inject, t } from \"alepha\";\nimport { $secure } from \"alepha/security\";\nimport { $action, okSchema } from \"alepha/server\";\nimport { $etag } from \"alepha/server/etag\";\nimport { FileAccessProvider } from \"../providers/FileAccessProvider.ts\";\nimport { fileQuerySchema } from \"../schemas/fileQuerySchema.ts\";\nimport { fileResourceSchema } from \"../schemas/fileResourceSchema.ts\";\nimport { FileService } from \"../services/FileService.ts\";\n\n/**\n * REST API controller for file management operations.\n * Provides endpoints for uploading, downloading, listing, and deleting files.\n */\nexport class FileController {\n protected readonly url = \"/files\";\n protected readonly group = \"files\";\n protected readonly fileService = $inject(FileService);\n protected readonly fileAccess = $inject(FileAccessProvider);\n\n /**\n * GET /files - Lists files with optional filtering and pagination.\n * Supports filtering by bucket and tags.\n */\n public readonly findFiles = $action({\n path: this.url,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:read\"] })],\n description: \"List files with filtering and pagination\",\n schema: {\n query: fileQuerySchema,\n response: t.page(fileResourceSchema),\n },\n handler: ({ query }) => this.fileService.findFiles(query),\n });\n\n /**\n * DELETE /files/:id - Deletes a file from both storage and database.\n * Removes the file from the bucket and cleans up the database record.\n */\n public readonly deleteFile = $action({\n method: \"DELETE\",\n path: `${this.url}/:id`,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:delete\"] })],\n description: \"Delete a file\",\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n response: okSchema,\n },\n handler: ({ params }) => this.fileService.deleteFile(params.id),\n });\n\n /**\n * POST /files/delete - Delete many files in one request, batching the\n * underlying bucket calls per bucket (R2/S3 batch where supported).\n */\n public readonly deleteFiles = $action({\n method: \"POST\",\n path: `${this.url}/delete`,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:delete\"] })],\n description: \"Delete many files\",\n schema: {\n body: t.object({\n ids: t.array(t.uuid(), { minItems: 1, maxItems: 1000 }),\n }),\n response: t.object({\n deleted: t.array(t.string()),\n }),\n },\n handler: async ({ body }) => {\n const deleted = await this.fileService.deleteFiles(body.ids);\n return { deleted };\n },\n });\n\n /**\n * POST /files - Uploads a new file to storage.\n * Creates a database record with metadata and calculates checksum.\n * Optionally specify bucket and expiration date.\n */\n public readonly uploadFile = $action({\n path: this.url,\n group: this.group,\n use: [$secure({ permissions: [\"file:create\"] })],\n description: \"Upload a new file\",\n schema: {\n body: t.object({\n file: t.file(),\n }),\n query: t.object({\n expirationDate: t.optional(t.datetime()),\n bucket: t.optional(t.string()),\n }),\n response: fileResourceSchema,\n },\n handler: async ({ body, user, query }) =>\n this.fileService.uploadFile(body.file, {\n user,\n ...query,\n }),\n });\n\n /**\n * PATCH /files/:id - Updates file metadata.\n * Allows updating name, tags, and expiration date without modifying file content.\n */\n public readonly updateFile = $action({\n method: \"PATCH\",\n path: `${this.url}/:id`,\n group: `admin:${this.group}`,\n use: [$secure({ permissions: [\"admin:file:update\"] })],\n description: \"Update file metadata\",\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n body: t.object({\n name: t.optional(t.string()),\n tags: t.optional(t.array(t.string())),\n expirationDate: t.optional(t.datetime()),\n }),\n response: fileResourceSchema,\n },\n handler: ({ params, body }) => this.fileService.updateFile(params.id, body),\n });\n\n /**\n * GET /files/:id - Streams/downloads a file by its ID.\n * Returns the file content with appropriate Content-Type header.\n *\n * Authorization is delegated to `FileAccessProvider.assertReadable`. The\n * default policy is creator-only — override the provider via DI to widen\n * access (e.g. avatars, shared attachments). See `FileAccessProvider`.\n *\n * Cache-Control is `private` because the per-user authorization decision\n * cannot be cached by shared proxies/CDNs. Client-side ETag still works.\n */\n public readonly streamFile = $action({\n path: `${this.url}/:id`,\n group: this.group,\n description: \"Download a file\",\n use: [\n $secure({ permissions: [\"file:read\"] }),\n $etag({\n control: {\n private: true,\n maxAge: [1, \"year\"],\n immutable: true,\n },\n }),\n ],\n schema: {\n params: t.object({\n id: t.uuid(),\n }),\n response: t.file(),\n },\n handler: async ({ params, user }) => {\n const file = await this.fileService.getFileById(params.id);\n await this.fileAccess.assertReadable(file, user);\n return await this.fileService.streamFile(file.id);\n },\n });\n}\n","import { $inject } from \"alepha\";\nimport { $scheduler } from \"alepha/scheduler\";\nimport { FileService } from \"../services/FileService.ts\";\n\nexport class FileJobs {\n protected readonly fileService = $inject(FileService);\n\n public readonly purgeFiles = $scheduler({\n name: \"api:files:purgeFiles\",\n description: \"Purge files that are marked for deletion\",\n cron: \"0 * * * *\", // Hourly at minute 0\n handler: async () => {\n const files = await this.fileService.findExpiredFiles();\n\n await Promise.all(\n files.map((file) => this.fileService.deleteFile(file.id)),\n );\n },\n });\n}\n","import { $module } from \"alepha\";\nimport { AlephaBucket } from \"alepha/bucket\";\nimport type { DurationLike } from \"alepha/datetime\";\nimport type { UserAccountToken } from \"alepha/security\";\nimport { AlephaServerEtag } from \"alepha/server/etag\";\nimport { AdminFileStatsController } from \"./controllers/AdminFileStatsController.ts\";\nimport { FileController } from \"./controllers/FileController.ts\";\nimport { FileJobs } from \"./jobs/FileJobs.ts\";\nimport { FileAccessProvider } from \"./providers/FileAccessProvider.ts\";\nimport { FileService } from \"./services/FileService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./controllers/AdminFileStatsController.ts\";\nexport * from \"./controllers/FileController.ts\";\nexport * from \"./entities/files.ts\";\nexport * from \"./jobs/FileJobs.ts\";\nexport * from \"./providers/FileAccessProvider.ts\";\nexport * from \"./schemas/storageStatsSchema.ts\";\nexport * from \"./services/FileService.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha/bucket\" {\n interface BucketFileOptions {\n /**\n * Time to live for the files in the bucket.\n */\n ttl?: DurationLike;\n\n /**\n * Tags for the bucket.\n */\n tags?: string[];\n\n /**\n * User performing the operation.\n */\n user?: UserAccountToken;\n\n /**\n * Whether to persist the file metadata in the database.\n *\n * @default true\n */\n persist?: boolean;\n }\n}\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * File management endpoints.\n *\n * **Features:**\n * - Upload/download endpoints\n * - File metadata storage\n * - TTL-based expiration\n * - Storage statistics\n *\n * @module alepha.api.files\n */\nexport const AlephaApiFiles = $module({\n name: \"alepha.api.files\",\n services: [\n FileController,\n AdminFileStatsController,\n FileJobs,\n FileService,\n FileAccessProvider,\n ],\n imports: [AlephaBucket, AlephaServerEtag],\n});\n"],"mappings":"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"}
@@ -7,6 +7,7 @@ import * as _$alepha_server0 from "alepha/server";
7
7
  import * as _$alepha_logger0 from "alepha/logger";
8
8
  import { LogEntry } from "alepha/logger";
9
9
  import * as _$alepha_orm0 from "alepha/orm";
10
+ import { CryptoProvider } from "alepha/crypto";
10
11
  import { DateTime, DateTimeProvider, DurationLike } from "alepha/datetime";
11
12
  import * as _$typebox from "typebox";
12
13
  import { BuildExtraConfigColumns, SQL } from "drizzle-orm";
@@ -624,6 +625,7 @@ declare class JobProvider {
624
625
  protected readonly dt: DateTimeProvider;
625
626
  protected readonly cronProvider: CronProvider;
626
627
  protected readonly lockProvider: LockProvider;
628
+ protected readonly crypto: CryptoProvider;
627
629
  protected readonly config: Readonly<{
628
630
  sweepCron: string;
629
631
  trimCron: string;
@@ -831,10 +833,10 @@ declare class JobProvider {
831
833
  triggeredByName?: string | undefined;
832
834
  cancelledBy?: string | undefined;
833
835
  cancelledByName?: string | undefined;
834
- jobName: string;
835
836
  id: string;
836
837
  createdAt: string;
837
838
  updatedAt: string;
839
+ jobName: string;
838
840
  status: "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
839
841
  priority: number;
840
842
  attempt: number;
@@ -915,7 +917,7 @@ type JobExecutionResource = Static<typeof jobExecutionResourceSchema>;
915
917
  declare const jobRegistrationSchema: _$typebox.TObject<{
916
918
  name: _$typebox.TString;
917
919
  description: _$typebox.TOptional<_$typebox.TString>;
918
- type: _$typebox.TUnsafe<"queue" | "direct" | "cron">;
920
+ type: _$typebox.TUnsafe<"cron" | "queue" | "direct">;
919
921
  priority: _$typebox.TUnsafe<"critical" | "high" | "normal" | "low">;
920
922
  cron: _$typebox.TOptional<_$typebox.TString>;
921
923
  timeout: _$typebox.TOptional<_$typebox.TString>;
@@ -1016,10 +1018,10 @@ declare class JobService {
1016
1018
  triggeredByName?: string | undefined;
1017
1019
  cancelledBy?: string | undefined;
1018
1020
  cancelledByName?: string | undefined;
1019
- jobName: string;
1020
1021
  id: string;
1021
1022
  createdAt: string;
1022
1023
  updatedAt: string;
1024
+ jobName: string;
1023
1025
  status: "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
1024
1026
  priority: number;
1025
1027
  attempt: number;
@@ -1053,10 +1055,10 @@ declare class JobService {
1053
1055
  triggeredByName?: string | undefined;
1054
1056
  cancelledBy?: string | undefined;
1055
1057
  cancelledByName?: string | undefined;
1056
- jobName: string;
1057
1058
  id: string;
1058
1059
  createdAt: string;
1059
1060
  updatedAt: string;
1061
+ jobName: string;
1060
1062
  status: "pending" | "running" | "scheduled" | "ok" | "error" | "cancelled";
1061
1063
  priority: number;
1062
1064
  attempt: number;
@@ -1101,7 +1103,7 @@ declare class AdminJobController {
1101
1103
  response: _$typebox.TArray<_$typebox.TObject<{
1102
1104
  name: _$typebox.TString;
1103
1105
  description: _$typebox.TOptional<_$typebox.TString>;
1104
- type: _$typebox.TUnsafe<"queue" | "direct" | "cron">;
1106
+ type: _$typebox.TUnsafe<"cron" | "queue" | "direct">;
1105
1107
  priority: _$typebox.TUnsafe<"critical" | "high" | "normal" | "low">;
1106
1108
  cron: _$typebox.TOptional<_$typebox.TString>;
1107
1109
  timeout: _$typebox.TOptional<_$typebox.TString>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/api/jobs/entities/jobExecutionEntity.ts","../../../src/api/jobs/primitives/$job.ts","../../../src/api/jobs/providers/JobDispatcher.ts","../../../src/api/jobs/providers/JobProvider.ts","../../../src/api/jobs/schemas/jobExecutionQuerySchema.ts","../../../src/api/jobs/schemas/jobExecutionResourceSchema.ts","../../../src/api/jobs/schemas/jobRegistrationSchema.ts","../../../src/api/jobs/services/JobService.ts","../../../src/api/jobs/controllers/AdminJobController.ts","../../../src/api/jobs/providers/DirectJobDispatcher.ts","../../../src/api/jobs/providers/JobQueueProvider.ts","../../../src/api/jobs/schemas/jobConfigAtom.ts","../../../src/api/jobs/schemas/triggerJobSchema.ts","../../../src/api/jobs/index.ts"],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/orm/core/schemas/insertSchema.ts","../../../src/orm/core/schemas/updateSchema.ts","../../../src/orm/core/primitives/$entity.ts","../../../src/orm/core/constants/PG_SYMBOLS.ts","../../../src/orm/core/helpers/pgAttr.ts","../../../src/orm/core/schemas/databaseEnvSchema.ts","../../../src/api/jobs/entities/jobExecutionEntity.ts","../../../src/api/jobs/primitives/$job.ts","../../../src/api/jobs/providers/JobDispatcher.ts","../../../src/api/jobs/providers/JobProvider.ts","../../../src/api/jobs/schemas/jobExecutionQuerySchema.ts","../../../src/api/jobs/schemas/jobExecutionResourceSchema.ts","../../../src/api/jobs/schemas/jobRegistrationSchema.ts","../../../src/api/jobs/services/JobService.ts","../../../src/api/jobs/controllers/AdminJobController.ts","../../../src/api/jobs/providers/DirectJobDispatcher.ts","../../../src/api/jobs/providers/JobQueueProvider.ts","../../../src/api/jobs/schemas/jobConfigAtom.ts","../../../src/api/jobs/schemas/triggerJobSchema.ts","../../../src/api/jobs/index.ts"],"mappings":"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"}
@@ -6,6 +6,7 @@ import { $secure } from "alepha/security";
6
6
  import { $action, NotFoundError, okSchema } from "alepha/server";
7
7
  import { $logger, logEntrySchema } from "alepha/logger";
8
8
  import { $entity, $repository, DbEntityNotFoundError, db, sql } from "alepha/orm";
9
+ import { CryptoProvider } from "alepha/crypto";
9
10
  import { DateTimeProvider } from "alepha/datetime";
10
11
  //#region ../../src/api/jobs/schemas/jobExecutionQuerySchema.ts
11
12
  const jobExecutionQuerySchema = t.object({
@@ -352,6 +353,7 @@ var JobProvider = class {
352
353
  dt = $inject(DateTimeProvider);
353
354
  cronProvider = $inject(CronProvider);
354
355
  lockProvider = $inject(LockProvider);
356
+ crypto = $inject(CryptoProvider);
355
357
  config = $state(jobConfig);
356
358
  /**
357
359
  * Resolved at first use (after the container is fully wired) — picks
@@ -444,7 +446,7 @@ var JobProvider = class {
444
446
  await this.enqueueCronExecution(registration, ctx);
445
447
  return;
446
448
  }
447
- const executionId = crypto.randomUUID();
449
+ const executionId = this.crypto.randomUUID();
448
450
  const promise = this.executeInline(registration, executionId, {
449
451
  payload: void 0,
450
452
  attempt: 1,
@@ -544,7 +546,7 @@ var JobProvider = class {
544
546
  */
545
547
  lockHolderIdValue;
546
548
  get lockHolderId() {
547
- if (!this.lockHolderIdValue) this.lockHolderIdValue = crypto.randomUUID();
549
+ if (!this.lockHolderIdValue) this.lockHolderIdValue = this.crypto.randomUUID();
548
550
  return this.lockHolderIdValue;
549
551
  }
550
552
  /**