alepha 0.14.2 → 0.14.4
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.
- package/README.md +1 -1
- package/dist/api/audits/index.browser.js +5 -5
- package/dist/api/audits/index.browser.js.map +1 -1
- package/dist/api/audits/index.d.ts +706 -785
- package/dist/api/audits/index.d.ts.map +1 -1
- package/dist/api/audits/index.js +13 -13
- package/dist/api/audits/index.js.map +1 -1
- package/dist/api/files/index.browser.js +5 -5
- package/dist/api/files/index.browser.js.map +1 -1
- package/dist/api/files/index.d.ts +58 -137
- package/dist/api/files/index.d.ts.map +1 -1
- package/dist/api/files/index.js +71 -71
- package/dist/api/files/index.js.map +1 -1
- package/dist/api/jobs/index.browser.js +5 -5
- package/dist/api/jobs/index.browser.js.map +1 -1
- package/dist/api/jobs/index.d.ts +29 -108
- package/dist/api/jobs/index.d.ts.map +1 -1
- package/dist/api/jobs/index.js +10 -10
- package/dist/api/jobs/index.js.map +1 -1
- package/dist/api/notifications/index.browser.js +10 -10
- package/dist/api/notifications/index.browser.js.map +1 -1
- package/dist/api/notifications/index.d.ts +504 -171
- package/dist/api/notifications/index.d.ts.map +1 -1
- package/dist/api/notifications/index.js +12 -12
- package/dist/api/notifications/index.js.map +1 -1
- package/dist/api/parameters/index.browser.js +163 -10
- package/dist/api/parameters/index.browser.js.map +1 -1
- package/dist/api/parameters/index.d.ts +277 -351
- package/dist/api/parameters/index.d.ts.map +1 -1
- package/dist/api/parameters/index.js +196 -91
- package/dist/api/parameters/index.js.map +1 -1
- package/dist/api/users/index.browser.js +19 -19
- package/dist/api/users/index.browser.js.map +1 -1
- package/dist/api/users/index.d.ts +787 -852
- package/dist/api/users/index.d.ts.map +1 -1
- package/dist/api/users/index.js +827 -596
- package/dist/api/users/index.js.map +1 -1
- package/dist/api/verifications/index.browser.js +6 -6
- package/dist/api/verifications/index.browser.js.map +1 -1
- package/dist/api/verifications/index.d.ts +128 -128
- package/dist/api/verifications/index.d.ts.map +1 -1
- package/dist/api/verifications/index.js +6 -6
- package/dist/api/verifications/index.js.map +1 -1
- package/dist/bin/index.d.ts +1 -2
- package/dist/bin/index.js +0 -1
- package/dist/bin/index.js.map +1 -1
- package/dist/cli/index.d.ts +252 -131
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +595 -395
- package/dist/cli/index.js.map +1 -1
- package/dist/command/index.d.ts +46 -11
- package/dist/command/index.d.ts.map +1 -1
- package/dist/command/index.js +99 -19
- package/dist/command/index.js.map +1 -1
- package/dist/core/index.browser.js +40 -22
- package/dist/core/index.browser.js.map +1 -1
- package/dist/core/index.d.ts +45 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +40 -22
- package/dist/core/index.js.map +1 -1
- package/dist/core/index.native.js +40 -22
- package/dist/core/index.native.js.map +1 -1
- package/dist/fake/index.js +195 -168
- package/dist/fake/index.js.map +1 -1
- package/dist/file/index.d.ts +8 -0
- package/dist/file/index.d.ts.map +1 -1
- package/dist/file/index.js +3 -0
- package/dist/file/index.js.map +1 -1
- package/dist/logger/index.d.ts +1 -1
- package/dist/logger/index.d.ts.map +1 -1
- package/dist/logger/index.js +12 -2
- package/dist/logger/index.js.map +1 -1
- package/dist/mcp/index.js +1 -1
- package/dist/mcp/index.js.map +1 -1
- package/dist/orm/index.d.ts +59 -195
- package/dist/orm/index.d.ts.map +1 -1
- package/dist/orm/index.js +201 -430
- package/dist/orm/index.js.map +1 -1
- package/dist/security/index.d.ts +1 -1
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +1 -1
- package/dist/security/index.js.map +1 -1
- package/dist/server/auth/index.d.ts +171 -155
- package/dist/server/auth/index.d.ts.map +1 -1
- package/dist/server/auth/index.js +0 -1
- package/dist/server/auth/index.js.map +1 -1
- package/dist/server/cache/index.d.ts +12 -0
- package/dist/server/cache/index.d.ts.map +1 -1
- package/dist/server/cache/index.js +55 -2
- package/dist/server/cache/index.js.map +1 -1
- package/dist/server/compress/index.d.ts +6 -0
- package/dist/server/compress/index.d.ts.map +1 -1
- package/dist/server/compress/index.js +38 -1
- package/dist/server/compress/index.js.map +1 -1
- package/dist/server/core/index.browser.js +2 -2
- package/dist/server/core/index.browser.js.map +1 -1
- package/dist/server/core/index.d.ts +10 -10
- package/dist/server/core/index.d.ts.map +1 -1
- package/dist/server/core/index.js +7 -4
- package/dist/server/core/index.js.map +1 -1
- package/dist/server/links/index.browser.js +22 -6
- package/dist/server/links/index.browser.js.map +1 -1
- package/dist/server/links/index.d.ts +46 -44
- package/dist/server/links/index.d.ts.map +1 -1
- package/dist/server/links/index.js +24 -41
- package/dist/server/links/index.js.map +1 -1
- package/dist/server/static/index.d.ts.map +1 -1
- package/dist/server/static/index.js +4 -0
- package/dist/server/static/index.js.map +1 -1
- package/dist/server/swagger/index.d.ts +2 -1
- package/dist/server/swagger/index.d.ts.map +1 -1
- package/dist/server/swagger/index.js +9 -5
- package/dist/server/swagger/index.js.map +1 -1
- package/dist/vite/index.d.ts +101 -106
- package/dist/vite/index.d.ts.map +1 -1
- package/dist/vite/index.js +574 -503
- package/dist/vite/index.js.map +1 -1
- package/dist/websocket/index.d.ts +7 -7
- package/package.json +7 -7
- package/src/api/audits/controllers/{AuditController.ts → AdminAuditController.ts} +5 -6
- package/src/api/audits/entities/audits.ts +5 -5
- package/src/api/audits/index.browser.ts +1 -1
- package/src/api/audits/index.ts +3 -3
- package/src/api/audits/primitives/$audit.spec.ts +276 -0
- package/src/api/audits/services/AuditService.spec.ts +495 -0
- package/src/api/files/__tests__/$bucket.spec.ts +91 -0
- package/src/api/files/controllers/AdminFileStatsController.spec.ts +166 -0
- package/src/api/files/controllers/{StorageStatsController.ts → AdminFileStatsController.ts} +2 -2
- package/src/api/files/controllers/FileController.spec.ts +558 -0
- package/src/api/files/controllers/FileController.ts +4 -5
- package/src/api/files/entities/files.ts +5 -5
- package/src/api/files/index.browser.ts +1 -1
- package/src/api/files/index.ts +4 -4
- package/src/api/files/jobs/FileJobs.spec.ts +52 -0
- package/src/api/files/services/FileService.spec.ts +109 -0
- package/src/api/jobs/__tests__/JobController.spec.ts +343 -0
- package/src/api/jobs/controllers/{JobController.ts → AdminJobController.ts} +2 -2
- package/src/api/jobs/entities/jobExecutions.ts +5 -5
- package/src/api/jobs/index.ts +3 -3
- package/src/api/jobs/primitives/$job.spec.ts +476 -0
- package/src/api/notifications/controllers/{NotificationController.ts → AdminNotificationController.ts} +4 -5
- package/src/api/notifications/entities/notifications.ts +5 -5
- package/src/api/notifications/index.browser.ts +1 -1
- package/src/api/notifications/index.ts +4 -4
- package/src/api/parameters/controllers/{ConfigController.ts → AdminConfigController.ts} +46 -107
- package/src/api/parameters/entities/parameters.ts +7 -17
- package/src/api/parameters/index.ts +3 -3
- package/src/api/parameters/primitives/$config.spec.ts +356 -0
- package/src/api/parameters/schemas/activateConfigBodySchema.ts +12 -0
- package/src/api/parameters/schemas/checkScheduledResponseSchema.ts +8 -0
- package/src/api/parameters/schemas/configCurrentResponseSchema.ts +13 -0
- package/src/api/parameters/schemas/configHistoryResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/configNameParamSchema.ts +10 -0
- package/src/api/parameters/schemas/configNamesResponseSchema.ts +8 -0
- package/src/api/parameters/schemas/configTreeNodeSchema.ts +13 -0
- package/src/api/parameters/schemas/configVersionParamSchema.ts +9 -0
- package/src/api/parameters/schemas/configVersionResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/configsByStatusResponseSchema.ts +9 -0
- package/src/api/parameters/schemas/createConfigVersionBodySchema.ts +24 -0
- package/src/api/parameters/schemas/index.ts +15 -0
- package/src/api/parameters/schemas/parameterResponseSchema.ts +26 -0
- package/src/api/parameters/schemas/parameterStatusSchema.ts +13 -0
- package/src/api/parameters/schemas/rollbackConfigBodySchema.ts +15 -0
- package/src/api/parameters/schemas/statusParamSchema.ts +9 -0
- package/src/api/users/__tests__/EmailVerification.spec.ts +369 -0
- package/src/api/users/__tests__/PasswordReset.spec.ts +550 -0
- package/src/api/users/controllers/AdminIdentityController.spec.ts +365 -0
- package/src/api/users/controllers/{IdentityController.ts → AdminIdentityController.ts} +3 -4
- package/src/api/users/controllers/AdminSessionController.spec.ts +274 -0
- package/src/api/users/controllers/{SessionController.ts → AdminSessionController.ts} +3 -4
- package/src/api/users/controllers/AdminUserController.spec.ts +372 -0
- package/src/api/users/controllers/AdminUserController.ts +116 -0
- package/src/api/users/controllers/UserController.ts +4 -107
- package/src/api/users/controllers/UserRealmController.ts +3 -0
- package/src/api/users/entities/identities.ts +6 -6
- package/src/api/users/entities/sessions.ts +6 -6
- package/src/api/users/entities/users.ts +9 -9
- package/src/api/users/index.ts +9 -6
- package/src/api/users/primitives/$userRealm.ts +13 -8
- package/src/api/users/services/CredentialService.spec.ts +509 -0
- package/src/api/users/services/CredentialService.ts +46 -0
- package/src/api/users/services/IdentityService.ts +15 -0
- package/src/api/users/services/RegistrationService.spec.ts +630 -0
- package/src/api/users/services/RegistrationService.ts +18 -0
- package/src/api/users/services/SessionService.spec.ts +301 -0
- package/src/api/users/services/SessionService.ts +110 -1
- package/src/api/users/services/UserService.ts +67 -2
- package/src/api/verifications/__tests__/CodeVerification.spec.ts +318 -0
- package/src/api/verifications/__tests__/LinkVerification.spec.ts +279 -0
- package/src/api/verifications/entities/verifications.ts +6 -6
- package/src/api/verifications/jobs/VerificationJobs.spec.ts +50 -0
- package/src/batch/__tests__/startup-buffering.spec.ts +458 -0
- package/src/batch/primitives/$batch.spec.ts +766 -0
- package/src/batch/providers/BatchProvider.spec.ts +786 -0
- package/src/bin/index.ts +0 -1
- package/src/bucket/__tests__/shared.ts +194 -0
- package/src/bucket/primitives/$bucket.spec.ts +104 -0
- package/src/bucket/providers/FileStorageProvider.spec.ts +13 -0
- package/src/bucket/providers/LocalFileStorageProvider.spec.ts +77 -0
- package/src/bucket/providers/MemoryFileStorageProvider.spec.ts +82 -0
- package/src/cache/core/__tests__/shared.ts +377 -0
- package/src/cache/core/primitives/$cache.spec.ts +111 -0
- package/src/cache/redis/__tests__/cache-redis.spec.ts +70 -0
- package/src/cli/apps/AlephaCli.ts +25 -6
- package/src/cli/atoms/buildOptions.ts +88 -0
- package/src/cli/commands/build.ts +32 -69
- package/src/cli/commands/db.ts +0 -4
- package/src/cli/commands/dev.ts +34 -10
- package/src/cli/commands/gen/changelog.spec.ts +315 -0
- package/src/cli/commands/{changelog.ts → gen/changelog.ts} +9 -9
- package/src/cli/commands/gen/env.ts +53 -0
- package/src/cli/commands/gen/openapi.ts +71 -0
- package/src/cli/commands/gen/resource.ts +15 -0
- package/src/cli/commands/gen.ts +24 -0
- package/src/cli/commands/init.ts +2 -1
- package/src/cli/commands/root.ts +12 -3
- package/src/cli/commands/test.ts +0 -1
- package/src/cli/commands/typecheck.ts +5 -0
- package/src/cli/commands/verify.ts +1 -1
- package/src/cli/defineConfig.ts +49 -7
- package/src/cli/index.ts +2 -2
- package/src/cli/services/AlephaCliUtils.ts +105 -55
- package/src/cli/services/GitMessageParser.ts +1 -1
- package/src/command/helpers/Asker.spec.ts +127 -0
- package/src/command/helpers/Runner.spec.ts +126 -0
- package/src/command/helpers/Runner.ts +1 -1
- package/src/command/primitives/$command.spec.ts +1588 -0
- package/src/command/primitives/$command.ts +0 -6
- package/src/command/providers/CliProvider.ts +75 -27
- package/src/core/Alepha.ts +87 -0
- package/src/core/__tests__/Alepha-emit.spec.ts +22 -0
- package/src/core/__tests__/Alepha-graph.spec.ts +93 -0
- package/src/core/__tests__/Alepha-has.spec.ts +41 -0
- package/src/core/__tests__/Alepha-inject.spec.ts +93 -0
- package/src/core/__tests__/Alepha-register.spec.ts +81 -0
- package/src/core/__tests__/Alepha-start.spec.ts +176 -0
- package/src/core/__tests__/Alepha-with.spec.ts +14 -0
- package/src/core/__tests__/TypeBox-usecases.spec.ts +35 -0
- package/src/core/__tests__/TypeBoxLocale.spec.ts +15 -0
- package/src/core/__tests__/descriptor.spec.ts +34 -0
- package/src/core/__tests__/fixtures/A.ts +5 -0
- package/src/core/__tests__/pagination.spec.ts +77 -0
- package/src/core/helpers/jsonSchemaToTypeBox.ts +2 -2
- package/src/core/primitives/$atom.spec.ts +43 -0
- package/src/core/primitives/$hook.spec.ts +130 -0
- package/src/core/primitives/$inject.spec.ts +175 -0
- package/src/core/primitives/$module.spec.ts +115 -0
- package/src/core/providers/CodecManager.spec.ts +740 -0
- package/src/core/providers/EventManager.spec.ts +762 -0
- package/src/core/providers/EventManager.ts +4 -0
- package/src/core/providers/StateManager.spec.ts +365 -0
- package/src/core/providers/TypeProvider.spec.ts +1607 -0
- package/src/core/providers/TypeProvider.ts +20 -26
- package/src/datetime/primitives/$interval.spec.ts +103 -0
- package/src/datetime/providers/DateTimeProvider.spec.ts +86 -0
- package/src/email/primitives/$email.spec.ts +175 -0
- package/src/email/providers/LocalEmailProvider.spec.ts +341 -0
- package/src/fake/__tests__/keyName.example.ts +40 -0
- package/src/fake/__tests__/keyName.spec.ts +152 -0
- package/src/fake/__tests__/module.example.ts +32 -0
- package/src/fake/providers/FakeProvider.spec.ts +438 -0
- package/src/file/providers/FileSystemProvider.ts +8 -0
- package/src/file/providers/NodeFileSystemProvider.spec.ts +418 -0
- package/src/file/providers/NodeFileSystemProvider.ts +5 -0
- package/src/file/services/FileDetector.spec.ts +591 -0
- package/src/lock/core/__tests__/shared.ts +190 -0
- package/src/lock/core/providers/MemoryLockProvider.spec.ts +25 -0
- package/src/lock/redis/providers/RedisLockProvider.spec.ts +25 -0
- package/src/logger/__tests__/SimpleFormatterProvider.spec.ts +109 -0
- package/src/logger/index.ts +15 -3
- package/src/logger/primitives/$logger.spec.ts +108 -0
- package/src/logger/services/Logger.spec.ts +295 -0
- package/src/mcp/__tests__/errors.spec.ts +175 -0
- package/src/mcp/__tests__/integration.spec.ts +450 -0
- package/src/mcp/helpers/jsonrpc.spec.ts +380 -0
- package/src/mcp/primitives/$prompt.spec.ts +468 -0
- package/src/mcp/primitives/$resource.spec.ts +390 -0
- package/src/mcp/primitives/$tool.spec.ts +406 -0
- package/src/mcp/providers/McpServerProvider.spec.ts +797 -0
- package/src/mcp/transports/StdioMcpTransport.ts +1 -1
- package/src/orm/__tests__/$repository-crud.spec.ts +276 -0
- package/src/orm/__tests__/$repository-hooks.spec.ts +325 -0
- package/src/orm/__tests__/$repository-orderBy.spec.ts +128 -0
- package/src/orm/__tests__/$repository-pagination-sort.spec.ts +149 -0
- package/src/orm/__tests__/$repository-save.spec.ts +37 -0
- package/src/orm/__tests__/ModelBuilder-integration.spec.ts +490 -0
- package/src/orm/__tests__/ModelBuilder-types.spec.ts +186 -0
- package/src/orm/__tests__/PostgresProvider.spec.ts +46 -0
- package/src/orm/__tests__/delete-returning.spec.ts +256 -0
- package/src/orm/__tests__/deletedAt.spec.ts +80 -0
- package/src/orm/__tests__/enums.spec.ts +315 -0
- package/src/orm/__tests__/execute.spec.ts +72 -0
- package/src/orm/__tests__/fixtures/bigEntitySchema.ts +65 -0
- package/src/orm/__tests__/fixtures/userEntitySchema.ts +27 -0
- package/src/orm/__tests__/joins.spec.ts +1114 -0
- package/src/orm/__tests__/page.spec.ts +287 -0
- package/src/orm/__tests__/primaryKey.spec.ts +87 -0
- package/src/orm/__tests__/query-date-encoding.spec.ts +402 -0
- package/src/orm/__tests__/ref-auto-onDelete.spec.ts +156 -0
- package/src/orm/__tests__/references.spec.ts +102 -0
- package/src/orm/__tests__/security.spec.ts +710 -0
- package/src/orm/__tests__/sqlite.spec.ts +111 -0
- package/src/orm/__tests__/string-operators.spec.ts +429 -0
- package/src/orm/__tests__/timestamps.spec.ts +388 -0
- package/src/orm/__tests__/validation.spec.ts +183 -0
- package/src/orm/__tests__/version.spec.ts +64 -0
- package/src/orm/helpers/parseQueryString.spec.ts +196 -0
- package/src/orm/index.ts +2 -8
- package/src/orm/primitives/$repository.spec.ts +137 -0
- package/src/orm/primitives/$sequence.spec.ts +29 -0
- package/src/orm/primitives/$transaction.spec.ts +82 -0
- package/src/orm/providers/drivers/BunPostgresProvider.ts +3 -3
- package/src/orm/providers/drivers/BunSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/CloudflareD1Provider.ts +1 -1
- package/src/orm/providers/drivers/DatabaseProvider.ts +1 -1
- package/src/orm/providers/drivers/NodePostgresProvider.ts +3 -3
- package/src/orm/providers/drivers/NodeSqliteProvider.ts +1 -1
- package/src/orm/providers/drivers/PglitePostgresProvider.ts +2 -2
- package/src/orm/services/ModelBuilder.spec.ts +575 -0
- package/src/orm/services/Repository.spec.ts +137 -0
- package/src/queue/core/__tests__/shared.ts +143 -0
- package/src/queue/core/providers/MemoryQueueProvider.spec.ts +23 -0
- package/src/queue/core/providers/WorkerProvider.spec.ts +394 -0
- package/src/queue/redis/providers/RedisQueueProvider.spec.ts +23 -0
- package/src/redis/__tests__/redis.spec.ts +58 -0
- package/src/retry/primitives/$retry.spec.ts +234 -0
- package/src/retry/providers/RetryProvider.spec.ts +438 -0
- package/src/router/__tests__/match.spec.ts +252 -0
- package/src/router/providers/RouterProvider.spec.ts +197 -0
- package/src/scheduler/__tests__/$scheduler-cron.spec.ts +25 -0
- package/src/scheduler/__tests__/$scheduler-interval.spec.ts +25 -0
- package/src/scheduler/__tests__/shared.ts +77 -0
- package/src/security/__tests__/bug-1-wildcard-after-start.spec.ts +229 -0
- package/src/security/__tests__/bug-2-password-validation.spec.ts +245 -0
- package/src/security/__tests__/bug-3-regex-vulnerability.spec.ts +407 -0
- package/src/security/__tests__/bug-4-oauth2-validation.spec.ts +439 -0
- package/src/security/__tests__/multi-layer-permissions.spec.ts +522 -0
- package/src/security/primitives/$permission.spec.ts +30 -0
- package/src/security/primitives/$permission.ts +2 -2
- package/src/security/primitives/$realm.spec.ts +101 -0
- package/src/security/primitives/$role.spec.ts +52 -0
- package/src/security/primitives/$serviceAccount.spec.ts +61 -0
- package/src/security/providers/SecurityProvider.spec.ts +350 -0
- package/src/server/auth/providers/ServerAuthProvider.ts +0 -2
- package/src/server/cache/providers/ServerCacheProvider.spec.ts +1125 -0
- package/src/server/cache/providers/ServerCacheProvider.ts +94 -9
- package/src/server/compress/providers/ServerCompressProvider.spec.ts +31 -0
- package/src/server/compress/providers/ServerCompressProvider.ts +63 -2
- package/src/server/cookies/providers/ServerCookiesProvider.spec.ts +253 -0
- package/src/server/core/__tests__/ServerRouterProvider-getRoutes.spec.ts +334 -0
- package/src/server/core/__tests__/ServerRouterProvider-requestId.spec.ts +129 -0
- package/src/server/core/helpers/ServerReply.ts +2 -2
- package/src/server/core/primitives/$action.spec.ts +191 -0
- package/src/server/core/primitives/$route.spec.ts +65 -0
- package/src/server/core/providers/ServerBodyParserProvider.spec.ts +93 -0
- package/src/server/core/providers/ServerLoggerProvider.spec.ts +100 -0
- package/src/server/core/providers/ServerProvider.ts +14 -2
- package/src/server/core/services/HttpClient.spec.ts +123 -0
- package/src/server/core/services/UserAgentParser.spec.ts +111 -0
- package/src/server/cors/providers/ServerCorsProvider.spec.ts +481 -0
- package/src/server/health/providers/ServerHealthProvider.spec.ts +22 -0
- package/src/server/helmet/providers/ServerHelmetProvider.spec.ts +105 -0
- package/src/server/links/__tests__/$action.spec.ts +238 -0
- package/src/server/links/__tests__/fixtures/CrudApp.ts +122 -0
- package/src/server/links/__tests__/requestId.spec.ts +120 -0
- package/src/server/links/primitives/$remote.spec.ts +228 -0
- package/src/server/links/providers/LinkProvider.spec.ts +54 -0
- package/src/server/links/providers/LinkProvider.ts +49 -3
- package/src/server/links/providers/ServerLinksProvider.ts +1 -53
- package/src/server/links/schemas/apiLinksResponseSchema.ts +7 -0
- package/src/server/metrics/providers/ServerMetricsProvider.spec.ts +25 -0
- package/src/server/multipart/providers/ServerMultipartProvider.spec.ts +528 -0
- package/src/server/proxy/primitives/$proxy.spec.ts +87 -0
- package/src/server/rate-limit/__tests__/ActionRateLimit.spec.ts +211 -0
- package/src/server/rate-limit/providers/ServerRateLimitProvider.spec.ts +344 -0
- package/src/server/security/__tests__/BasicAuth.spec.ts +684 -0
- package/src/server/security/__tests__/ServerSecurityProvider-realm.spec.ts +388 -0
- package/src/server/security/providers/ServerSecurityProvider.spec.ts +123 -0
- package/src/server/static/primitives/$serve.spec.ts +193 -0
- package/src/server/static/providers/ServerStaticProvider.ts +10 -0
- package/src/server/swagger/__tests__/ui.spec.ts +52 -0
- package/src/server/swagger/primitives/$swagger.spec.ts +193 -0
- package/src/server/swagger/providers/ServerSwaggerProvider.ts +19 -12
- package/src/sms/primitives/$sms.spec.ts +165 -0
- package/src/sms/providers/LocalSmsProvider.spec.ts +224 -0
- package/src/sms/providers/MemorySmsProvider.spec.ts +193 -0
- package/src/thread/primitives/$thread.spec.ts +186 -0
- package/src/topic/core/__tests__/shared.ts +144 -0
- package/src/topic/core/providers/MemoryTopicProvider.spec.ts +23 -0
- package/src/topic/redis/providers/RedisTopicProvider.spec.ts +23 -0
- package/src/vite/helpers/importViteReact.ts +13 -0
- package/src/vite/index.ts +1 -21
- package/src/vite/plugins/viteAlephaDev.ts +32 -5
- package/src/vite/plugins/viteAlephaSsrPreload.ts +222 -0
- package/src/vite/tasks/buildClient.ts +11 -0
- package/src/vite/tasks/buildServer.ts +47 -3
- package/src/vite/tasks/devServer.ts +69 -0
- package/src/vite/tasks/index.ts +2 -1
- package/src/vite/tasks/runAlepha.ts +7 -1
- package/src/websocket/__tests__/$websocket-new.spec.ts +195 -0
- package/src/websocket/primitives/$channel.spec.ts +30 -0
- package/src/cli/assets/viteConfigTs.ts +0 -14
- package/src/cli/commands/run.ts +0 -24
- package/src/vite/plugins/viteAlepha.ts +0 -37
- package/src/vite/plugins/viteAlephaBuild.ts +0 -281
package/dist/file/index.d.ts
CHANGED
|
@@ -204,6 +204,13 @@ interface LsOptions {
|
|
|
204
204
|
* FileSystem interface providing utilities for working with files.
|
|
205
205
|
*/
|
|
206
206
|
declare abstract class FileSystemProvider {
|
|
207
|
+
/**
|
|
208
|
+
* Joins multiple path segments into a single path.
|
|
209
|
+
*
|
|
210
|
+
* @param paths - The path segments to join
|
|
211
|
+
* @returns The joined path
|
|
212
|
+
*/
|
|
213
|
+
abstract join(...paths: string[]): string;
|
|
207
214
|
/**
|
|
208
215
|
* Creates a FileLike object from various sources.
|
|
209
216
|
*
|
|
@@ -425,6 +432,7 @@ declare class FileDetector {
|
|
|
425
432
|
*/
|
|
426
433
|
declare class NodeFileSystemProvider implements FileSystemProvider {
|
|
427
434
|
protected detector: FileDetector;
|
|
435
|
+
join(...paths: string[]): string;
|
|
428
436
|
/**
|
|
429
437
|
* Creates a FileLike object from various sources.
|
|
430
438
|
*
|
package/dist/file/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/file/providers/FileSystemProvider.ts","../../src/file/services/FileDetector.ts","../../src/file/providers/NodeFileSystemProvider.ts","../../src/file/index.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAKiB,wBAAA;EAAA;AAkBjB;AAkBA;EAkBiB,GAAA,EAAA,MAAA;EAsBA;AAejB;AAkBA;EAsBiB,IAAA,CAAA,EAAA,MAAA;EAkBL;;;EAGR,IAAA,CAAA,EAAA,MAAA;;;;;AAKA,UA3Ia,yBAAA,CA2Ib;EAAgC;AAKpC;AAcA;EAciB,IAAA,EAAA,MAAA;EAcA;AAcjB;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/file/providers/FileSystemProvider.ts","../../src/file/services/FileDetector.ts","../../src/file/providers/NodeFileSystemProvider.ts","../../src/file/index.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/file/index.js
CHANGED
package/dist/file/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["fsRm","fsCp","fsMkdir","fsReadFile","fsWriteFile"],"sources":["../../src/file/providers/FileSystemProvider.ts","../../src/file/services/FileDetector.ts","../../src/file/providers/NodeFileSystemProvider.ts","../../src/file/index.ts"],"sourcesContent":["import type { FileLike, StreamLike } from \"alepha\";\n\n/**\n * Options for creating a file from a URL\n */\nexport interface CreateFileFromUrlOptions {\n /**\n * The URL to load the file from (file://, http://, or https://)\n */\n url: string;\n /**\n * The MIME type of the file (optional, will be detected from filename if not provided)\n */\n type?: string;\n /**\n * The name of the file (optional, will be extracted from URL if not provided)\n */\n name?: string;\n}\n\n/**\n * Options for creating a file from a path (URL with file:// scheme)\n */\nexport interface CreateFileFromPathOptions {\n /**\n * The path to the file on the local filesystem\n */\n path: string;\n /**\n * The MIME type of the file (optional, will be detected from filename if not provided)\n */\n type?: string;\n /**\n * The name of the file (optional, will be extracted from URL if not provided)\n */\n name?: string;\n}\n\n/**\n * Options for creating a file from a Buffer\n */\nexport interface CreateFileFromBufferOptions {\n /**\n * The Buffer containing the file data\n */\n buffer: Buffer;\n /**\n * The MIME type of the file (optional, will be detected from name if not provided)\n */\n type?: string;\n /**\n * The name of the file (required for proper content type detection)\n */\n name?: string;\n}\n\n/**\n * Options for creating a file from a stream\n */\nexport interface CreateFileFromStreamOptions {\n /**\n * The readable stream containing the file data\n */\n stream: StreamLike;\n /**\n * The MIME type of the file (optional, will be detected from name if not provided)\n */\n type?: string;\n /**\n * The name of the file (required for proper content type detection)\n */\n name?: string;\n /**\n * The size of the file in bytes (optional)\n */\n size?: number;\n}\n\n/**\n * Options for creating a file from text content\n */\nexport interface CreateFileFromTextOptions {\n /**\n * The text content to create the file from\n */\n text: string;\n /**\n * The MIME type of the file (default: text/plain)\n */\n type?: string;\n /**\n * The name of the file (default: \"file.txt\")\n */\n name?: string;\n}\n\nexport interface CreateFileFromResponseOptions {\n /**\n * The Response object containing the file data\n */\n response: Response;\n /**\n * Override the name (optional, uses filename from Content-Disposition header if not provided)\n */\n name?: string;\n /**\n * Override the MIME type (optional, uses file.type if not provided)\n */\n type?: string;\n}\n\n/**\n * Options for creating a file from a Web File object\n */\nexport interface CreateFileFromWebFileOptions {\n /**\n * The Web File object\n */\n file: File;\n /**\n * Override the MIME type (optional, uses file.type if not provided)\n */\n type?: string;\n /**\n * Override the name (optional, uses file.name if not provided)\n */\n name?: string;\n /**\n * Override the size (optional, uses file.size if not provided)\n */\n size?: number;\n}\n\n/**\n * Options for creating a file from an ArrayBuffer\n */\nexport interface CreateFileFromArrayBufferOptions {\n /**\n * The ArrayBuffer containing the file data\n */\n arrayBuffer: ArrayBuffer;\n /**\n * The MIME type of the file (optional, will be detected from name if not provided)\n */\n type?: string;\n /**\n * The name of the file (required for proper content type detection)\n */\n name?: string;\n}\n\n/**\n * Union type for all createFile options\n */\nexport type CreateFileOptions =\n | CreateFileFromUrlOptions\n | CreateFileFromPathOptions\n | CreateFileFromBufferOptions\n | CreateFileFromStreamOptions\n | CreateFileFromTextOptions\n | CreateFileFromWebFileOptions\n | CreateFileFromResponseOptions\n | CreateFileFromArrayBufferOptions;\n\n/**\n * Options for rm (remove) operation\n */\nexport interface RmOptions {\n /**\n * If true, removes directories and their contents recursively\n */\n recursive?: boolean;\n /**\n * If true, no error will be thrown if the path does not exist\n */\n force?: boolean;\n}\n\n/**\n * Options for cp (copy) operation\n */\nexport interface CpOptions {\n /**\n * If true, copy directories recursively\n */\n recursive?: boolean;\n /**\n * If true, overwrite existing destination\n */\n force?: boolean;\n}\n\n/**\n * Options for mkdir operation\n */\nexport interface MkdirOptions {\n /**\n * If true, creates parent directories as needed\n */\n recursive?: boolean;\n /**\n * File mode (permission and sticky bits)\n */\n mode?: number;\n}\n\n/**\n * Options for ls (list) operation\n */\nexport interface LsOptions {\n /**\n * If true, list contents of directories recursively\n */\n recursive?: boolean;\n /**\n * If true, include hidden files (starting with .)\n */\n hidden?: boolean;\n}\n\n/**\n * FileSystem interface providing utilities for working with files.\n */\nexport abstract class FileSystemProvider {\n /**\n * Creates a FileLike object from various sources.\n *\n * @param options - Options for creating the file\n * @returns A FileLike object\n */\n abstract createFile(options: CreateFileOptions): FileLike;\n\n /**\n * Removes a file or directory.\n *\n * @param path - The path to remove\n * @param options - Remove options\n */\n abstract rm(path: string, options?: RmOptions): Promise<void>;\n\n /**\n * Copies a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n * @param options - Copy options\n */\n abstract cp(src: string, dest: string, options?: CpOptions): Promise<void>;\n\n /**\n * Moves/renames a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n */\n abstract mv(src: string, dest: string): Promise<void>;\n\n /**\n * Creates a directory.\n *\n * @param path - The directory path to create\n * @param options - Mkdir options\n */\n abstract mkdir(path: string, options?: MkdirOptions): Promise<void>;\n\n /**\n * Lists files in a directory.\n *\n * @param path - The directory path to list\n * @param options - List options\n * @returns Array of filenames\n */\n abstract ls(path: string, options?: LsOptions): Promise<string[]>;\n\n /**\n * Checks if a file or directory exists.\n *\n * @param path - The path to check\n * @returns True if the path exists, false otherwise\n */\n abstract exists(path: string): Promise<boolean>;\n\n /**\n * Reads the content of a file.\n *\n * @param path - The file path to read\n * @returns The file content as a Buffer\n */\n abstract readFile(path: string): Promise<Buffer>;\n\n /**\n * Writes data to a file.\n *\n * @param path - The file path to write to\n * @param data - The data to write (Buffer or string)\n */\n abstract writeFile(\n path: string,\n data: Uint8Array | Buffer | string | FileLike,\n ): Promise<void>;\n}\n","import { Readable } from \"node:stream\";\n\nexport interface FileTypeResult {\n /**\n * The detected MIME type\n */\n mimeType: string;\n /**\n * The detected file extension\n */\n extension: string;\n /**\n * Whether the file type was verified by magic bytes\n */\n verified: boolean;\n /**\n * The stream (potentially wrapped to allow re-reading)\n */\n stream: Readable;\n}\n\n/**\n * Service for detecting file types and getting content types.\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n *\n * // Get content type from filename\n * const mimeType = detector.getContentType(\"image.png\"); // \"image/png\"\n *\n * // Detect file type by magic bytes\n * const stream = createReadStream('image.png');\n * const result = await detector.detectFileType(stream, 'image.png');\n * console.log(result.mimeType); // 'image/png'\n * console.log(result.verified); // true if magic bytes match\n * ```\n */\nexport class FileDetector {\n /**\n * Magic byte signatures for common file formats.\n * Each signature is represented as an array of bytes or null (wildcard).\n */\n protected static readonly MAGIC_BYTES: Record<\n string,\n { signature: (number | null)[]; mimeType: string }[]\n > = {\n // Images\n png: [\n {\n signature: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],\n mimeType: \"image/png\",\n },\n ],\n jpg: [\n { signature: [0xff, 0xd8, 0xff, 0xe0], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe1], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe2], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe3], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe8], mimeType: \"image/jpeg\" },\n ],\n jpeg: [\n { signature: [0xff, 0xd8, 0xff, 0xe0], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe1], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe2], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe3], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe8], mimeType: \"image/jpeg\" },\n ],\n gif: [\n {\n signature: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61],\n mimeType: \"image/gif\",\n }, // GIF87a\n {\n signature: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61],\n mimeType: \"image/gif\",\n }, // GIF89a\n ],\n webp: [\n {\n signature: [\n 0x52,\n 0x49,\n 0x46,\n 0x46,\n null,\n null,\n null,\n null,\n 0x57,\n 0x45,\n 0x42,\n 0x50,\n ],\n mimeType: \"image/webp\",\n },\n ],\n bmp: [{ signature: [0x42, 0x4d], mimeType: \"image/bmp\" }],\n ico: [{ signature: [0x00, 0x00, 0x01, 0x00], mimeType: \"image/x-icon\" }],\n tiff: [\n { signature: [0x49, 0x49, 0x2a, 0x00], mimeType: \"image/tiff\" }, // Little-endian\n { signature: [0x4d, 0x4d, 0x00, 0x2a], mimeType: \"image/tiff\" }, // Big-endian\n ],\n tif: [\n { signature: [0x49, 0x49, 0x2a, 0x00], mimeType: \"image/tiff\" },\n { signature: [0x4d, 0x4d, 0x00, 0x2a], mimeType: \"image/tiff\" },\n ],\n\n // Documents\n pdf: [\n {\n signature: [0x25, 0x50, 0x44, 0x46, 0x2d],\n mimeType: \"application/pdf\",\n },\n ], // %PDF-\n zip: [\n { signature: [0x50, 0x4b, 0x03, 0x04], mimeType: \"application/zip\" },\n { signature: [0x50, 0x4b, 0x05, 0x06], mimeType: \"application/zip\" },\n { signature: [0x50, 0x4b, 0x07, 0x08], mimeType: \"application/zip\" },\n ],\n\n // Archives\n rar: [\n {\n signature: [0x52, 0x61, 0x72, 0x21, 0x1a, 0x07],\n mimeType: \"application/vnd.rar\",\n },\n ],\n \"7z\": [\n {\n signature: [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c],\n mimeType: \"application/x-7z-compressed\",\n },\n ],\n tar: [\n {\n signature: [0x75, 0x73, 0x74, 0x61, 0x72],\n mimeType: \"application/x-tar\",\n },\n ],\n gz: [{ signature: [0x1f, 0x8b], mimeType: \"application/gzip\" }],\n tgz: [{ signature: [0x1f, 0x8b], mimeType: \"application/gzip\" }],\n\n // Audio\n mp3: [\n { signature: [0xff, 0xfb], mimeType: \"audio/mpeg\" },\n { signature: [0xff, 0xf3], mimeType: \"audio/mpeg\" },\n { signature: [0xff, 0xf2], mimeType: \"audio/mpeg\" },\n { signature: [0x49, 0x44, 0x33], mimeType: \"audio/mpeg\" }, // ID3\n ],\n wav: [\n {\n signature: [\n 0x52,\n 0x49,\n 0x46,\n 0x46,\n null,\n null,\n null,\n null,\n 0x57,\n 0x41,\n 0x56,\n 0x45,\n ],\n mimeType: \"audio/wav\",\n },\n ],\n ogg: [{ signature: [0x4f, 0x67, 0x67, 0x53], mimeType: \"audio/ogg\" }],\n flac: [{ signature: [0x66, 0x4c, 0x61, 0x43], mimeType: \"audio/flac\" }], // fLaC\n\n // Video\n mp4: [\n {\n signature: [null, null, null, null, 0x66, 0x74, 0x79, 0x70],\n mimeType: \"video/mp4\",\n }, // ftyp\n {\n signature: [\n null,\n null,\n null,\n null,\n 0x66,\n 0x74,\n 0x79,\n 0x70,\n 0x69,\n 0x73,\n 0x6f,\n 0x6d,\n ],\n mimeType: \"video/mp4\",\n }, // ftypisom\n {\n signature: [\n null,\n null,\n null,\n null,\n 0x66,\n 0x74,\n 0x79,\n 0x70,\n 0x6d,\n 0x70,\n 0x34,\n 0x32,\n ],\n mimeType: \"video/mp4\",\n }, // ftypmp42\n ],\n webm: [{ signature: [0x1a, 0x45, 0xdf, 0xa3], mimeType: \"video/webm\" }],\n avi: [\n {\n signature: [\n 0x52,\n 0x49,\n 0x46,\n 0x46,\n null,\n null,\n null,\n null,\n 0x41,\n 0x56,\n 0x49,\n 0x20,\n ],\n mimeType: \"video/x-msvideo\",\n },\n ],\n mov: [\n {\n signature: [\n null,\n null,\n null,\n null,\n 0x66,\n 0x74,\n 0x79,\n 0x70,\n 0x71,\n 0x74,\n 0x20,\n 0x20,\n ],\n mimeType: \"video/quicktime\",\n },\n ],\n mkv: [\n { signature: [0x1a, 0x45, 0xdf, 0xa3], mimeType: \"video/x-matroska\" },\n ],\n\n // Office (DOCX, XLSX, PPTX are all ZIP-based)\n docx: [\n {\n signature: [0x50, 0x4b, 0x03, 0x04],\n mimeType:\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n },\n ],\n xlsx: [\n {\n signature: [0x50, 0x4b, 0x03, 0x04],\n mimeType:\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n },\n ],\n pptx: [\n {\n signature: [0x50, 0x4b, 0x03, 0x04],\n mimeType:\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n },\n ],\n doc: [\n {\n signature: [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n mimeType: \"application/msword\",\n },\n ],\n xls: [\n {\n signature: [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n mimeType: \"application/vnd.ms-excel\",\n },\n ],\n ppt: [\n {\n signature: [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n mimeType: \"application/vnd.ms-powerpoint\",\n },\n ],\n };\n\n /**\n * All possible format signatures for checking against actual file content\n */\n protected static readonly ALL_SIGNATURES = Object.entries(\n FileDetector.MAGIC_BYTES,\n ).flatMap(([ext, signatures]) => signatures.map((sig) => ({ ext, ...sig })));\n\n /**\n * MIME type map for file extensions.\n *\n * Can be used to get the content type of file based on its extension.\n * Feel free to add more mime types in your project!\n */\n public static readonly mimeMap: Record<string, string> = {\n // Documents\n json: \"application/json\",\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n xml: \"application/xml\",\n csv: \"text/csv\",\n pdf: \"application/pdf\",\n md: \"text/markdown\",\n markdown: \"text/markdown\",\n rtf: \"application/rtf\",\n\n // Styles and scripts\n css: \"text/css\",\n js: \"application/javascript\",\n mjs: \"application/javascript\",\n ts: \"application/typescript\",\n jsx: \"text/jsx\",\n tsx: \"text/tsx\",\n\n // Archives\n zip: \"application/zip\",\n rar: \"application/vnd.rar\",\n \"7z\": \"application/x-7z-compressed\",\n tar: \"application/x-tar\",\n gz: \"application/gzip\",\n tgz: \"application/gzip\",\n\n // Images\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n bmp: \"image/bmp\",\n ico: \"image/x-icon\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n\n // Audio\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n m4a: \"audio/mp4\",\n aac: \"audio/aac\",\n flac: \"audio/flac\",\n\n // Video\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n avi: \"video/x-msvideo\",\n mov: \"video/quicktime\",\n wmv: \"video/x-ms-wmv\",\n flv: \"video/x-flv\",\n mkv: \"video/x-matroska\",\n\n // Office\n doc: \"application/msword\",\n docx: \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n xls: \"application/vnd.ms-excel\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n ppt: \"application/vnd.ms-powerpoint\",\n pptx: \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n\n // Fonts\n woff: \"font/woff\",\n woff2: \"font/woff2\",\n ttf: \"font/ttf\",\n otf: \"font/otf\",\n eot: \"application/vnd.ms-fontobject\",\n };\n\n /**\n * Reverse MIME type map for looking up extensions from MIME types.\n * Prefers shorter, more common extensions when multiple exist.\n */\n protected static readonly reverseMimeMap: Record<string, string> = (() => {\n const reverse: Record<string, string> = {};\n // Process in order so common extensions come first\n for (const [ext, mimeType] of Object.entries(FileDetector.mimeMap)) {\n // Only set if not already set (prefer first/shorter extension)\n if (!reverse[mimeType]) {\n reverse[mimeType] = ext;\n }\n }\n return reverse;\n })();\n\n /**\n * Returns the file extension for a given MIME type.\n *\n * @param mimeType - The MIME type to look up\n * @returns The file extension (without dot), or \"bin\" if not found\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n * const ext = detector.getExtensionFromMimeType(\"image/png\"); // \"png\"\n * const ext2 = detector.getExtensionFromMimeType(\"application/octet-stream\"); // \"bin\"\n * ```\n */\n getExtensionFromMimeType(mimeType: string): string {\n return FileDetector.reverseMimeMap[mimeType] || \"bin\";\n }\n /**\n * Returns the content type of file based on its filename.\n *\n * @param filename - The filename to check\n * @returns The MIME type\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n * const mimeType = detector.getContentType(\"image.png\"); // \"image/png\"\n * ```\n */\n getContentType(filename: string): string {\n const ext = filename.toLowerCase().split(\".\").pop() || \"\";\n return FileDetector.mimeMap[ext] || \"application/octet-stream\";\n }\n\n /**\n * Detects the file type by checking magic bytes against the stream content.\n *\n * @param stream - The readable stream to check\n * @param filename - The filename (used to get the extension)\n * @returns File type information including MIME type, extension, and verification status\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n * const stream = createReadStream('image.png');\n * const result = await detector.detectFileType(stream, 'image.png');\n * console.log(result.mimeType); // 'image/png'\n * console.log(result.verified); // true if magic bytes match\n * ```\n */\n async detectFileType(\n stream: Readable,\n filename: string,\n ): Promise<FileTypeResult> {\n // Get the expected MIME type from the filename extension\n const expectedMimeType = this.getContentType(filename);\n\n // Extract extension - only if filename contains a dot\n const lastDotIndex = filename.lastIndexOf(\".\");\n const ext =\n lastDotIndex > 0\n ? filename.substring(lastDotIndex + 1).toLowerCase()\n : \"\";\n\n // Read the first 16 bytes (enough for most magic byte checks)\n const { buffer, stream: newStream } = await this.peekBytes(stream, 16);\n\n // First, check if the extension's expected signature matches\n const expectedSignatures = FileDetector.MAGIC_BYTES[ext];\n if (expectedSignatures) {\n for (const { signature, mimeType } of expectedSignatures) {\n if (this.matchesSignature(buffer, signature)) {\n return {\n mimeType,\n extension: ext,\n verified: true,\n stream: newStream,\n };\n }\n }\n }\n\n // If the expected signature didn't match, try all other signatures\n for (const {\n ext: detectedExt,\n signature,\n mimeType,\n } of FileDetector.ALL_SIGNATURES) {\n if (detectedExt !== ext && this.matchesSignature(buffer, signature)) {\n return {\n mimeType,\n extension: detectedExt,\n verified: true,\n stream: newStream,\n };\n }\n }\n\n // If no magic bytes matched, fall back to extension-based detection\n // or return binary if extension is not recognized\n return {\n mimeType: expectedMimeType,\n extension: ext,\n verified: false,\n stream: newStream,\n };\n }\n\n /**\n * Reads all bytes from a stream and returns the first N bytes along with a new stream containing all data.\n * This approach reads the entire stream upfront to avoid complex async handling issues.\n *\n * @protected\n */\n protected async peekBytes(\n stream: Readable,\n numBytes: number,\n ): Promise<{ buffer: Buffer; stream: Readable }> {\n const chunks: Buffer[] = [];\n\n // Read the entire stream\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n const allData = Buffer.concat(chunks);\n const buffer = allData.subarray(0, numBytes);\n\n // Create a new stream with all the data\n const newStream = Readable.from(allData);\n\n return { buffer, stream: newStream };\n }\n\n /**\n * Checks if a buffer matches a magic byte signature.\n *\n * @protected\n */\n protected matchesSignature(\n buffer: Buffer,\n signature: (number | null)[],\n ): boolean {\n if (buffer.length < signature.length) {\n return false;\n }\n\n for (let i = 0; i < signature.length; i++) {\n if (signature[i] !== null && buffer[i] !== signature[i]) {\n return false;\n }\n }\n\n return true;\n }\n}\n","import { createReadStream } from \"node:fs\";\nimport {\n access,\n copyFile,\n cp as fsCp,\n mkdir as fsMkdir,\n readFile as fsReadFile,\n rm as fsRm,\n writeFile as fsWriteFile,\n readdir,\n rename,\n stat,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { PassThrough, Readable } from \"node:stream\";\nimport type { ReadableStream as NodeWebStream } from \"node:stream/web\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n $inject,\n AlephaError,\n type FileLike,\n isFileLike,\n type StreamLike,\n} from \"alepha\";\nimport { FileDetector } from \"../services/FileDetector.ts\";\nimport type {\n CpOptions,\n CreateFileOptions,\n FileSystemProvider,\n LsOptions,\n MkdirOptions,\n RmOptions,\n} from \"./FileSystemProvider.ts\";\n\n/**\n * Node.js implementation of FileSystem interface.\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Create from URL\n * const file1 = fs.createFile({ url: \"file:///path/to/file.png\" });\n *\n * // Create from Buffer\n * const file2 = fs.createFile({ buffer: Buffer.from(\"hello\"), name: \"hello.txt\" });\n *\n * // Create from text\n * const file3 = fs.createFile({ text: \"Hello, world!\", name: \"greeting.txt\" });\n *\n * // File operations\n * await fs.mkdir(\"/tmp/mydir\", { recursive: true });\n * await fs.cp(\"/src/file.txt\", \"/dest/file.txt\");\n * await fs.mv(\"/old/path.txt\", \"/new/path.txt\");\n * const files = await fs.ls(\"/tmp\");\n * await fs.rm(\"/tmp/file.txt\");\n * ```\n */\nexport class NodeFileSystemProvider implements FileSystemProvider {\n protected detector = $inject(FileDetector);\n /**\n * Creates a FileLike object from various sources.\n *\n * @param options - Options for creating the file\n * @returns A FileLike object\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // From URL\n * const file1 = fs.createFile({ url: \"https://example.com/image.png\" });\n *\n * // From Buffer\n * const file2 = fs.createFile({\n * buffer: Buffer.from(\"hello\"),\n * name: \"hello.txt\",\n * type: \"text/plain\"\n * });\n *\n * // From text\n * const file3 = fs.createFile({ text: \"Hello!\", name: \"greeting.txt\" });\n *\n * // From stream with detection\n * const stream = createReadStream(\"/path/to/file.png\");\n * const file4 = fs.createFile({ stream, name: \"image.png\" });\n * ```\n */\n createFile(options: CreateFileOptions): FileLike {\n if (\"path\" in options) {\n const path = options.path;\n const filename = path.split(\"/\").pop() || \"file\";\n return this.createFileFromUrl(`file://${path}`, {\n type: options.type,\n name: options.name || filename,\n });\n }\n\n // Handle URL\n if (\"url\" in options) {\n return this.createFileFromUrl(options.url, {\n type: options.type,\n name: options.name,\n });\n }\n\n if (\"response\" in options) {\n if (!options.response.body) {\n throw new AlephaError(\"Response has no body stream\");\n }\n const res = options.response;\n // guess size from content-length header if available\n const sizeHeader = res.headers.get(\"content-length\");\n const size = sizeHeader ? parseInt(sizeHeader, 10) : undefined;\n // guess name from content-disposition header if available\n let name = options.name;\n const contentDisposition = res.headers.get(\"content-disposition\");\n if (contentDisposition && !name) {\n const match = contentDisposition.match(/filename=\"?([^\"]+)\"?/);\n if (match) {\n name = match[1];\n }\n }\n // guess type from content-type header if available\n const type = options.type || res.headers.get(\"content-type\") || undefined;\n return this.createFileFromStream(options.response.body, {\n type,\n name,\n size,\n });\n }\n\n // Handle Web File\n if (\"file\" in options) {\n return this.createFileFromWebFile(options.file, {\n type: options.type,\n name: options.name,\n size: options.size,\n });\n }\n\n // Handle Buffer\n if (\"buffer\" in options) {\n return this.createFileFromBuffer(options.buffer, {\n type: options.type,\n name: options.name,\n });\n }\n\n // Handle ArrayBuffer\n if (\"arrayBuffer\" in options) {\n return this.createFileFromBuffer(Buffer.from(options.arrayBuffer), {\n type: options.type,\n name: options.name,\n });\n }\n\n // Handle text\n if (\"text\" in options) {\n return this.createFileFromBuffer(Buffer.from(options.text, \"utf-8\"), {\n type: options.type || \"text/plain\",\n name: options.name || \"file.txt\",\n });\n }\n\n // Handle stream\n if (\"stream\" in options) {\n return this.createFileFromStream(options.stream, {\n type: options.type,\n name: options.name,\n size: options.size,\n });\n }\n\n throw new AlephaError(\n \"Invalid createFile options: no valid source provided\",\n );\n }\n\n /**\n * Removes a file or directory.\n *\n * @param path - The path to remove\n * @param options - Remove options\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Remove a file\n * await fs.rm(\"/tmp/file.txt\");\n *\n * // Remove a directory recursively\n * await fs.rm(\"/tmp/mydir\", { recursive: true });\n *\n * // Remove with force (no error if doesn't exist)\n * await fs.rm(\"/tmp/maybe-exists.txt\", { force: true });\n * ```\n */\n async rm(path: string, options?: RmOptions): Promise<void> {\n await fsRm(path, options);\n }\n\n /**\n * Copies a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n * @param options - Copy options\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Copy a file\n * await fs.cp(\"/src/file.txt\", \"/dest/file.txt\");\n *\n * // Copy a directory recursively\n * await fs.cp(\"/src/dir\", \"/dest/dir\", { recursive: true });\n *\n * // Copy with force (overwrite existing)\n * await fs.cp(\"/src/file.txt\", \"/dest/file.txt\", { force: true });\n * ```\n */\n async cp(src: string, dest: string, options?: CpOptions): Promise<void> {\n // Check if source is a directory\n const srcStat = await stat(src);\n\n if (srcStat.isDirectory()) {\n if (!options?.recursive) {\n throw new Error(\n `Cannot copy directory without recursive option: ${src}`,\n );\n }\n // Use Node.js cp function for recursive directory copy\n await fsCp(src, dest, {\n recursive: true,\n force: options?.force ?? false,\n });\n } else {\n // For files, use copyFile\n await copyFile(src, dest);\n }\n }\n\n /**\n * Moves/renames a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Move/rename a file\n * await fs.mv(\"/old/path.txt\", \"/new/path.txt\");\n *\n * // Move a directory\n * await fs.mv(\"/old/dir\", \"/new/dir\");\n * ```\n */\n async mv(src: string, dest: string): Promise<void> {\n await rename(src, dest);\n }\n\n /**\n * Creates a directory.\n *\n * @param path - The directory path to create\n * @param options - Mkdir options\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Create a directory\n * await fs.mkdir(\"/tmp/mydir\");\n *\n * // Create nested directories\n * await fs.mkdir(\"/tmp/path/to/dir\", { recursive: true });\n *\n * // Create with specific permissions\n * await fs.mkdir(\"/tmp/mydir\", { mode: 0o755 });\n * ```\n */\n async mkdir(path: string, options?: MkdirOptions): Promise<void> {\n await fsMkdir(path, options);\n }\n\n /**\n * Lists files in a directory.\n *\n * @param path - The directory path to list\n * @param options - List options\n * @returns Array of filenames\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // List files in a directory\n * const files = await fs.ls(\"/tmp\");\n * console.log(files); // [\"file1.txt\", \"file2.txt\", \"subdir\"]\n *\n * // List with hidden files\n * const allFiles = await fs.ls(\"/tmp\", { hidden: true });\n *\n * // List recursively\n * const allFilesRecursive = await fs.ls(\"/tmp\", { recursive: true });\n * ```\n */\n async ls(path: string, options?: LsOptions): Promise<string[]> {\n const entries = await readdir(path);\n\n // Filter out hidden files if not requested\n const filteredEntries = options?.hidden\n ? entries\n : entries.filter((e) => !e.startsWith(\".\"));\n\n // If recursive, get all nested files\n if (options?.recursive) {\n const allFiles: string[] = [];\n\n for (const entry of filteredEntries) {\n const fullPath = join(path, entry);\n const entryStat = await stat(fullPath);\n\n if (entryStat.isDirectory()) {\n // Add directory entry\n allFiles.push(entry);\n // Recursively get files from subdirectory\n const subFiles = await this.ls(fullPath, options);\n allFiles.push(...subFiles.map((f) => join(entry, f)));\n } else {\n allFiles.push(entry);\n }\n }\n\n return allFiles;\n }\n\n return filteredEntries;\n }\n\n /**\n * Checks if a file or directory exists.\n *\n * @param path - The path to check\n * @returns True if the path exists, false otherwise\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * if (await fs.exists(\"/tmp/file.txt\")) {\n * console.log(\"File exists\");\n * }\n * ```\n */\n async exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Reads the content of a file.\n *\n * @param path - The file path to read\n * @returns The file content as a Buffer\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * const buffer = await fs.readFile(\"/tmp/file.txt\");\n * console.log(buffer.toString(\"utf-8\"));\n * ```\n */\n async readFile(path: string): Promise<Buffer> {\n return await fsReadFile(path);\n }\n\n /**\n * Writes data to a file.\n *\n * @param path - The file path to write to\n * @param data - The data to write (Buffer or string)\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Write string\n * await fs.writeFile(\"/tmp/file.txt\", \"Hello, world!\");\n *\n * // Write Buffer\n * await fs.writeFile(\"/tmp/file.bin\", Buffer.from([0x01, 0x02, 0x03]));\n * ```\n */\n async writeFile(\n path: string,\n data: Uint8Array | Buffer | string | FileLike,\n ): Promise<void> {\n if (isFileLike(data)) {\n await fsWriteFile(path, Readable.from(data.stream()));\n return;\n }\n await fsWriteFile(path, data);\n }\n\n /**\n * Creates a FileLike object from a Web File.\n *\n * @protected\n */\n protected createFileFromWebFile(\n source: File,\n options: {\n type?: string;\n name?: string;\n size?: number;\n } = {},\n ): FileLike {\n const name = options.name ?? source.name;\n return {\n name,\n type: options.type ?? (source.type || this.detector.getContentType(name)),\n size: options.size ?? source.size ?? 0,\n lastModified: source.lastModified || Date.now(),\n stream: () => source.stream(),\n arrayBuffer: async (): Promise<ArrayBuffer> => {\n return await source.arrayBuffer();\n },\n text: async (): Promise<string> => {\n return await source.text();\n },\n };\n }\n\n /**\n * Creates a FileLike object from a Buffer.\n *\n * @protected\n */\n protected createFileFromBuffer(\n source: Buffer,\n options: {\n type?: string;\n name?: string;\n } = {},\n ): FileLike {\n const name: string = options.name ?? \"file\";\n return {\n name,\n type: options.type ?? this.detector.getContentType(options.name ?? name),\n size: source.byteLength,\n lastModified: Date.now(),\n stream: (): Readable => Readable.from(source),\n arrayBuffer: async (): Promise<ArrayBuffer> => {\n return this.bufferToArrayBuffer(source);\n },\n text: async (): Promise<string> => {\n return source.toString(\"utf-8\");\n },\n };\n }\n\n /**\n * Creates a FileLike object from a stream.\n *\n * @protected\n */\n protected createFileFromStream(\n source: StreamLike,\n options: {\n type?: string;\n name?: string;\n size?: number;\n } = {},\n ): FileLike & { _buffer: null | Buffer } {\n let buffer: Buffer | null = null;\n\n return {\n name: options.name ?? \"file\",\n type:\n options.type ?? this.detector.getContentType(options.name ?? \"file\"),\n size: options.size ?? 0,\n lastModified: Date.now(),\n stream: () => source,\n _buffer: null as Buffer | null,\n arrayBuffer: async () => {\n buffer ??= await this.streamToBuffer(source);\n return this.bufferToArrayBuffer(buffer);\n },\n text: async () => {\n buffer ??= await this.streamToBuffer(source);\n return buffer.toString(\"utf-8\");\n },\n };\n }\n\n /**\n * Creates a FileLike object from a URL.\n *\n * @protected\n */\n protected createFileFromUrl(\n url: string,\n options: {\n type?: string;\n name?: string;\n } = {},\n ): FileLike {\n const parsedUrl = new URL(url);\n const filename =\n options.name || parsedUrl.pathname.split(\"/\").pop() || \"file\";\n let buffer: Buffer | null = null;\n\n return {\n name: filename,\n type: options.type ?? this.detector.getContentType(filename),\n size: 0, // Unknown size until loaded\n lastModified: Date.now(),\n stream: () => this.createStreamFromUrl(url),\n arrayBuffer: async () => {\n buffer ??= await this.loadFromUrl(url);\n return this.bufferToArrayBuffer(buffer);\n },\n text: async () => {\n buffer ??= await this.loadFromUrl(url);\n return buffer.toString(\"utf-8\");\n },\n filepath: url,\n };\n }\n\n /**\n * Gets a streaming response from a URL.\n *\n * @protected\n */\n protected getStreamingResponse(url: string): Readable {\n const stream = new PassThrough();\n\n fetch(url)\n .then((res) =>\n Readable.fromWeb(res.body as unknown as NodeWebStream).pipe(stream),\n )\n .catch((err) => stream.destroy(err));\n\n return stream;\n }\n\n /**\n * Loads data from a URL.\n *\n * @protected\n */\n protected async loadFromUrl(url: string): Promise<Buffer> {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol === \"file:\") {\n // Handle file:// URLs\n const filePath = fileURLToPath(url);\n return await fsReadFile(filePath);\n } else if (\n parsedUrl.protocol === \"http:\" ||\n parsedUrl.protocol === \"https:\"\n ) {\n // Handle HTTP/HTTPS URLs\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${url}: ${response.status} ${response.statusText}`,\n );\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n } else {\n throw new Error(`Unsupported protocol: ${parsedUrl.protocol}`);\n }\n }\n\n /**\n * Creates a stream from a URL.\n *\n * @protected\n */\n protected createStreamFromUrl(url: string): Readable {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol === \"file:\") {\n // For file:// URLs, create a stream that reads the file\n return createReadStream(fileURLToPath(url));\n } else if (\n parsedUrl.protocol === \"http:\" ||\n parsedUrl.protocol === \"https:\"\n ) {\n // For HTTP/HTTPS URLs, create a stream that fetches the content\n return this.getStreamingResponse(url);\n } else {\n throw new AlephaError(`Unsupported protocol: ${parsedUrl.protocol}`);\n }\n }\n\n /**\n * Converts a stream-like object to a Buffer.\n *\n * @protected\n */\n protected async streamToBuffer(streamLike: StreamLike): Promise<Buffer> {\n const stream =\n streamLike instanceof Readable\n ? streamLike\n : Readable.fromWeb(streamLike as NodeWebStream);\n\n return new Promise<Buffer>((resolve, reject) => {\n const buffer: any[] = [];\n stream.on(\"data\", (chunk) => buffer.push(Buffer.from(chunk)));\n stream.on(\"end\", () => resolve(Buffer.concat(buffer)));\n stream.on(\"error\", (err) =>\n reject(new AlephaError(\"Error converting stream\", { cause: err })),\n );\n });\n }\n\n /**\n * Converts a Node.js Buffer to an ArrayBuffer.\n *\n * @protected\n */\n protected bufferToArrayBuffer(buffer: Buffer): ArrayBuffer {\n return buffer.buffer.slice(\n buffer.byteOffset,\n buffer.byteOffset + buffer.byteLength,\n ) as ArrayBuffer;\n }\n}\n","import { $module } from \"alepha\";\nimport { FileSystemProvider } from \"./providers/FileSystemProvider.ts\";\nimport { NodeFileSystemProvider } from \"./providers/NodeFileSystemProvider.ts\";\nimport { FileDetector } from \"./services/FileDetector.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/FileSystemProvider.ts\";\nexport * from \"./providers/NodeFileSystemProvider.ts\";\nexport * from \"./services/FileDetector.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides file system capabilities for Alepha applications with support for multiple file sources and operations.\n *\n * The file module enables working with files from various sources (URLs, buffers, streams) and provides\n * utilities for file type detection, content type determination, and common file system operations.\n *\n * @see {@link FileDetector}\n * @see {@link FileSystemProvider}\n * @see {@link NodeFileSystemProvider}\n * @module alepha.file\n */\nexport const AlephaFile = $module({\n name: \"alepha.file\",\n primitives: [],\n services: [FileDetector, FileSystemProvider, NodeFileSystemProvider],\n register: (alepha) =>\n alepha.with({\n optional: true,\n provide: FileSystemProvider,\n use: NodeFileSystemProvider,\n }),\n});\n"],"mappings":";;;;;;;;;;;AA+NA,IAAsB,qBAAtB,MAAyC;;;;;;;;;;;;;;;;;;;;;ACzLzC,IAAa,eAAb,MAAa,aAAa;;;;;CAKxB,OAA0B,cAGtB;EAEF,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC3D,UAAU;GACX,CACF;EACD,KAAK;GACH;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAChE;EACD,MAAM;GACJ;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC/D;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAChE;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC/C,UAAU;GACX,EACD;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC/C,UAAU;GACX,CACF;EACD,MAAM,CACJ;GACE,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACD,UAAU;GACX,CACF;EACD,KAAK,CAAC;GAAE,WAAW,CAAC,IAAM,GAAK;GAAE,UAAU;GAAa,CAAC;EACzD,KAAK,CAAC;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAgB,CAAC;EACxE,MAAM,CACJ;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,EAC/D;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,CAChE;EACD,KAAK,CACH;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,EAC/D;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,CAChE;EAGD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAK;GACzC,UAAU;GACX,CACF;EACD,KAAK;GACH;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAmB;GACpE;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAmB;GACpE;IAAE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAK;IAAE,UAAU;IAAmB;GACrE;EAGD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC/C,UAAU;GACX,CACF;EACD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC/C,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAK;GACzC,UAAU;GACX,CACF;EACD,IAAI,CAAC;GAAE,WAAW,CAAC,IAAM,IAAK;GAAE,UAAU;GAAoB,CAAC;EAC/D,KAAK,CAAC;GAAE,WAAW,CAAC,IAAM,IAAK;GAAE,UAAU;GAAoB,CAAC;EAGhE,KAAK;GACH;IAAE,WAAW,CAAC,KAAM,IAAK;IAAE,UAAU;IAAc;GACnD;IAAE,WAAW,CAAC,KAAM,IAAK;IAAE,UAAU;IAAc;GACnD;IAAE,WAAW,CAAC,KAAM,IAAK;IAAE,UAAU;IAAc;GACnD;IAAE,WAAW;KAAC;KAAM;KAAM;KAAK;IAAE,UAAU;IAAc;GAC1D;EACD,KAAK,CACH;GACE,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACD,UAAU;GACX,CACF;EACD,KAAK,CAAC;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAa,CAAC;EACrE,MAAM,CAAC;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,CAAC;EAGvE,KAAK;GACH;IACE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAM;KAAM;KAAM;KAAM;KAAK;IAC3D,UAAU;IACX;GACD;IACE,WAAW;KACT;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD;IACD,UAAU;IACX;GACD;IACE,WAAW;KACT;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD;IACD,UAAU;IACX;GACF;EACD,MAAM,CAAC;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,CAAC;EACvE,KAAK,CACH;GACE,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACD,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACD,UAAU;GACX,CACF;EACD,KAAK,CACH;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAoB,CACtE;EAGD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GACnC,UACE;GACH,CACF;EACD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GACnC,UACE;GACH,CACF;EACD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GACnC,UACE;GACH,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC3D,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC3D,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;I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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["fsRm","fsCp","fsMkdir","fsReadFile","fsWriteFile"],"sources":["../../src/file/providers/FileSystemProvider.ts","../../src/file/services/FileDetector.ts","../../src/file/providers/NodeFileSystemProvider.ts","../../src/file/index.ts"],"sourcesContent":["import type { FileLike, StreamLike } from \"alepha\";\n\n/**\n * Options for creating a file from a URL\n */\nexport interface CreateFileFromUrlOptions {\n /**\n * The URL to load the file from (file://, http://, or https://)\n */\n url: string;\n /**\n * The MIME type of the file (optional, will be detected from filename if not provided)\n */\n type?: string;\n /**\n * The name of the file (optional, will be extracted from URL if not provided)\n */\n name?: string;\n}\n\n/**\n * Options for creating a file from a path (URL with file:// scheme)\n */\nexport interface CreateFileFromPathOptions {\n /**\n * The path to the file on the local filesystem\n */\n path: string;\n /**\n * The MIME type of the file (optional, will be detected from filename if not provided)\n */\n type?: string;\n /**\n * The name of the file (optional, will be extracted from URL if not provided)\n */\n name?: string;\n}\n\n/**\n * Options for creating a file from a Buffer\n */\nexport interface CreateFileFromBufferOptions {\n /**\n * The Buffer containing the file data\n */\n buffer: Buffer;\n /**\n * The MIME type of the file (optional, will be detected from name if not provided)\n */\n type?: string;\n /**\n * The name of the file (required for proper content type detection)\n */\n name?: string;\n}\n\n/**\n * Options for creating a file from a stream\n */\nexport interface CreateFileFromStreamOptions {\n /**\n * The readable stream containing the file data\n */\n stream: StreamLike;\n /**\n * The MIME type of the file (optional, will be detected from name if not provided)\n */\n type?: string;\n /**\n * The name of the file (required for proper content type detection)\n */\n name?: string;\n /**\n * The size of the file in bytes (optional)\n */\n size?: number;\n}\n\n/**\n * Options for creating a file from text content\n */\nexport interface CreateFileFromTextOptions {\n /**\n * The text content to create the file from\n */\n text: string;\n /**\n * The MIME type of the file (default: text/plain)\n */\n type?: string;\n /**\n * The name of the file (default: \"file.txt\")\n */\n name?: string;\n}\n\nexport interface CreateFileFromResponseOptions {\n /**\n * The Response object containing the file data\n */\n response: Response;\n /**\n * Override the name (optional, uses filename from Content-Disposition header if not provided)\n */\n name?: string;\n /**\n * Override the MIME type (optional, uses file.type if not provided)\n */\n type?: string;\n}\n\n/**\n * Options for creating a file from a Web File object\n */\nexport interface CreateFileFromWebFileOptions {\n /**\n * The Web File object\n */\n file: File;\n /**\n * Override the MIME type (optional, uses file.type if not provided)\n */\n type?: string;\n /**\n * Override the name (optional, uses file.name if not provided)\n */\n name?: string;\n /**\n * Override the size (optional, uses file.size if not provided)\n */\n size?: number;\n}\n\n/**\n * Options for creating a file from an ArrayBuffer\n */\nexport interface CreateFileFromArrayBufferOptions {\n /**\n * The ArrayBuffer containing the file data\n */\n arrayBuffer: ArrayBuffer;\n /**\n * The MIME type of the file (optional, will be detected from name if not provided)\n */\n type?: string;\n /**\n * The name of the file (required for proper content type detection)\n */\n name?: string;\n}\n\n/**\n * Union type for all createFile options\n */\nexport type CreateFileOptions =\n | CreateFileFromUrlOptions\n | CreateFileFromPathOptions\n | CreateFileFromBufferOptions\n | CreateFileFromStreamOptions\n | CreateFileFromTextOptions\n | CreateFileFromWebFileOptions\n | CreateFileFromResponseOptions\n | CreateFileFromArrayBufferOptions;\n\n/**\n * Options for rm (remove) operation\n */\nexport interface RmOptions {\n /**\n * If true, removes directories and their contents recursively\n */\n recursive?: boolean;\n /**\n * If true, no error will be thrown if the path does not exist\n */\n force?: boolean;\n}\n\n/**\n * Options for cp (copy) operation\n */\nexport interface CpOptions {\n /**\n * If true, copy directories recursively\n */\n recursive?: boolean;\n /**\n * If true, overwrite existing destination\n */\n force?: boolean;\n}\n\n/**\n * Options for mkdir operation\n */\nexport interface MkdirOptions {\n /**\n * If true, creates parent directories as needed\n */\n recursive?: boolean;\n /**\n * File mode (permission and sticky bits)\n */\n mode?: number;\n}\n\n/**\n * Options for ls (list) operation\n */\nexport interface LsOptions {\n /**\n * If true, list contents of directories recursively\n */\n recursive?: boolean;\n /**\n * If true, include hidden files (starting with .)\n */\n hidden?: boolean;\n}\n\n/**\n * FileSystem interface providing utilities for working with files.\n */\nexport abstract class FileSystemProvider {\n /**\n * Joins multiple path segments into a single path.\n *\n * @param paths - The path segments to join\n * @returns The joined path\n */\n abstract join(...paths: string[]): string;\n\n /**\n * Creates a FileLike object from various sources.\n *\n * @param options - Options for creating the file\n * @returns A FileLike object\n */\n abstract createFile(options: CreateFileOptions): FileLike;\n\n /**\n * Removes a file or directory.\n *\n * @param path - The path to remove\n * @param options - Remove options\n */\n abstract rm(path: string, options?: RmOptions): Promise<void>;\n\n /**\n * Copies a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n * @param options - Copy options\n */\n abstract cp(src: string, dest: string, options?: CpOptions): Promise<void>;\n\n /**\n * Moves/renames a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n */\n abstract mv(src: string, dest: string): Promise<void>;\n\n /**\n * Creates a directory.\n *\n * @param path - The directory path to create\n * @param options - Mkdir options\n */\n abstract mkdir(path: string, options?: MkdirOptions): Promise<void>;\n\n /**\n * Lists files in a directory.\n *\n * @param path - The directory path to list\n * @param options - List options\n * @returns Array of filenames\n */\n abstract ls(path: string, options?: LsOptions): Promise<string[]>;\n\n /**\n * Checks if a file or directory exists.\n *\n * @param path - The path to check\n * @returns True if the path exists, false otherwise\n */\n abstract exists(path: string): Promise<boolean>;\n\n /**\n * Reads the content of a file.\n *\n * @param path - The file path to read\n * @returns The file content as a Buffer\n */\n abstract readFile(path: string): Promise<Buffer>;\n\n /**\n * Writes data to a file.\n *\n * @param path - The file path to write to\n * @param data - The data to write (Buffer or string)\n */\n abstract writeFile(\n path: string,\n data: Uint8Array | Buffer | string | FileLike,\n ): Promise<void>;\n}\n","import { Readable } from \"node:stream\";\n\nexport interface FileTypeResult {\n /**\n * The detected MIME type\n */\n mimeType: string;\n /**\n * The detected file extension\n */\n extension: string;\n /**\n * Whether the file type was verified by magic bytes\n */\n verified: boolean;\n /**\n * The stream (potentially wrapped to allow re-reading)\n */\n stream: Readable;\n}\n\n/**\n * Service for detecting file types and getting content types.\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n *\n * // Get content type from filename\n * const mimeType = detector.getContentType(\"image.png\"); // \"image/png\"\n *\n * // Detect file type by magic bytes\n * const stream = createReadStream('image.png');\n * const result = await detector.detectFileType(stream, 'image.png');\n * console.log(result.mimeType); // 'image/png'\n * console.log(result.verified); // true if magic bytes match\n * ```\n */\nexport class FileDetector {\n /**\n * Magic byte signatures for common file formats.\n * Each signature is represented as an array of bytes or null (wildcard).\n */\n protected static readonly MAGIC_BYTES: Record<\n string,\n { signature: (number | null)[]; mimeType: string }[]\n > = {\n // Images\n png: [\n {\n signature: [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a],\n mimeType: \"image/png\",\n },\n ],\n jpg: [\n { signature: [0xff, 0xd8, 0xff, 0xe0], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe1], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe2], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe3], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe8], mimeType: \"image/jpeg\" },\n ],\n jpeg: [\n { signature: [0xff, 0xd8, 0xff, 0xe0], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe1], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe2], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe3], mimeType: \"image/jpeg\" },\n { signature: [0xff, 0xd8, 0xff, 0xe8], mimeType: \"image/jpeg\" },\n ],\n gif: [\n {\n signature: [0x47, 0x49, 0x46, 0x38, 0x37, 0x61],\n mimeType: \"image/gif\",\n }, // GIF87a\n {\n signature: [0x47, 0x49, 0x46, 0x38, 0x39, 0x61],\n mimeType: \"image/gif\",\n }, // GIF89a\n ],\n webp: [\n {\n signature: [\n 0x52,\n 0x49,\n 0x46,\n 0x46,\n null,\n null,\n null,\n null,\n 0x57,\n 0x45,\n 0x42,\n 0x50,\n ],\n mimeType: \"image/webp\",\n },\n ],\n bmp: [{ signature: [0x42, 0x4d], mimeType: \"image/bmp\" }],\n ico: [{ signature: [0x00, 0x00, 0x01, 0x00], mimeType: \"image/x-icon\" }],\n tiff: [\n { signature: [0x49, 0x49, 0x2a, 0x00], mimeType: \"image/tiff\" }, // Little-endian\n { signature: [0x4d, 0x4d, 0x00, 0x2a], mimeType: \"image/tiff\" }, // Big-endian\n ],\n tif: [\n { signature: [0x49, 0x49, 0x2a, 0x00], mimeType: \"image/tiff\" },\n { signature: [0x4d, 0x4d, 0x00, 0x2a], mimeType: \"image/tiff\" },\n ],\n\n // Documents\n pdf: [\n {\n signature: [0x25, 0x50, 0x44, 0x46, 0x2d],\n mimeType: \"application/pdf\",\n },\n ], // %PDF-\n zip: [\n { signature: [0x50, 0x4b, 0x03, 0x04], mimeType: \"application/zip\" },\n { signature: [0x50, 0x4b, 0x05, 0x06], mimeType: \"application/zip\" },\n { signature: [0x50, 0x4b, 0x07, 0x08], mimeType: \"application/zip\" },\n ],\n\n // Archives\n rar: [\n {\n signature: [0x52, 0x61, 0x72, 0x21, 0x1a, 0x07],\n mimeType: \"application/vnd.rar\",\n },\n ],\n \"7z\": [\n {\n signature: [0x37, 0x7a, 0xbc, 0xaf, 0x27, 0x1c],\n mimeType: \"application/x-7z-compressed\",\n },\n ],\n tar: [\n {\n signature: [0x75, 0x73, 0x74, 0x61, 0x72],\n mimeType: \"application/x-tar\",\n },\n ],\n gz: [{ signature: [0x1f, 0x8b], mimeType: \"application/gzip\" }],\n tgz: [{ signature: [0x1f, 0x8b], mimeType: \"application/gzip\" }],\n\n // Audio\n mp3: [\n { signature: [0xff, 0xfb], mimeType: \"audio/mpeg\" },\n { signature: [0xff, 0xf3], mimeType: \"audio/mpeg\" },\n { signature: [0xff, 0xf2], mimeType: \"audio/mpeg\" },\n { signature: [0x49, 0x44, 0x33], mimeType: \"audio/mpeg\" }, // ID3\n ],\n wav: [\n {\n signature: [\n 0x52,\n 0x49,\n 0x46,\n 0x46,\n null,\n null,\n null,\n null,\n 0x57,\n 0x41,\n 0x56,\n 0x45,\n ],\n mimeType: \"audio/wav\",\n },\n ],\n ogg: [{ signature: [0x4f, 0x67, 0x67, 0x53], mimeType: \"audio/ogg\" }],\n flac: [{ signature: [0x66, 0x4c, 0x61, 0x43], mimeType: \"audio/flac\" }], // fLaC\n\n // Video\n mp4: [\n {\n signature: [null, null, null, null, 0x66, 0x74, 0x79, 0x70],\n mimeType: \"video/mp4\",\n }, // ftyp\n {\n signature: [\n null,\n null,\n null,\n null,\n 0x66,\n 0x74,\n 0x79,\n 0x70,\n 0x69,\n 0x73,\n 0x6f,\n 0x6d,\n ],\n mimeType: \"video/mp4\",\n }, // ftypisom\n {\n signature: [\n null,\n null,\n null,\n null,\n 0x66,\n 0x74,\n 0x79,\n 0x70,\n 0x6d,\n 0x70,\n 0x34,\n 0x32,\n ],\n mimeType: \"video/mp4\",\n }, // ftypmp42\n ],\n webm: [{ signature: [0x1a, 0x45, 0xdf, 0xa3], mimeType: \"video/webm\" }],\n avi: [\n {\n signature: [\n 0x52,\n 0x49,\n 0x46,\n 0x46,\n null,\n null,\n null,\n null,\n 0x41,\n 0x56,\n 0x49,\n 0x20,\n ],\n mimeType: \"video/x-msvideo\",\n },\n ],\n mov: [\n {\n signature: [\n null,\n null,\n null,\n null,\n 0x66,\n 0x74,\n 0x79,\n 0x70,\n 0x71,\n 0x74,\n 0x20,\n 0x20,\n ],\n mimeType: \"video/quicktime\",\n },\n ],\n mkv: [\n { signature: [0x1a, 0x45, 0xdf, 0xa3], mimeType: \"video/x-matroska\" },\n ],\n\n // Office (DOCX, XLSX, PPTX are all ZIP-based)\n docx: [\n {\n signature: [0x50, 0x4b, 0x03, 0x04],\n mimeType:\n \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n },\n ],\n xlsx: [\n {\n signature: [0x50, 0x4b, 0x03, 0x04],\n mimeType:\n \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n },\n ],\n pptx: [\n {\n signature: [0x50, 0x4b, 0x03, 0x04],\n mimeType:\n \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n },\n ],\n doc: [\n {\n signature: [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n mimeType: \"application/msword\",\n },\n ],\n xls: [\n {\n signature: [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n mimeType: \"application/vnd.ms-excel\",\n },\n ],\n ppt: [\n {\n signature: [0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1],\n mimeType: \"application/vnd.ms-powerpoint\",\n },\n ],\n };\n\n /**\n * All possible format signatures for checking against actual file content\n */\n protected static readonly ALL_SIGNATURES = Object.entries(\n FileDetector.MAGIC_BYTES,\n ).flatMap(([ext, signatures]) => signatures.map((sig) => ({ ext, ...sig })));\n\n /**\n * MIME type map for file extensions.\n *\n * Can be used to get the content type of file based on its extension.\n * Feel free to add more mime types in your project!\n */\n public static readonly mimeMap: Record<string, string> = {\n // Documents\n json: \"application/json\",\n txt: \"text/plain\",\n html: \"text/html\",\n htm: \"text/html\",\n xml: \"application/xml\",\n csv: \"text/csv\",\n pdf: \"application/pdf\",\n md: \"text/markdown\",\n markdown: \"text/markdown\",\n rtf: \"application/rtf\",\n\n // Styles and scripts\n css: \"text/css\",\n js: \"application/javascript\",\n mjs: \"application/javascript\",\n ts: \"application/typescript\",\n jsx: \"text/jsx\",\n tsx: \"text/tsx\",\n\n // Archives\n zip: \"application/zip\",\n rar: \"application/vnd.rar\",\n \"7z\": \"application/x-7z-compressed\",\n tar: \"application/x-tar\",\n gz: \"application/gzip\",\n tgz: \"application/gzip\",\n\n // Images\n png: \"image/png\",\n jpg: \"image/jpeg\",\n jpeg: \"image/jpeg\",\n gif: \"image/gif\",\n webp: \"image/webp\",\n svg: \"image/svg+xml\",\n bmp: \"image/bmp\",\n ico: \"image/x-icon\",\n tiff: \"image/tiff\",\n tif: \"image/tiff\",\n\n // Audio\n mp3: \"audio/mpeg\",\n wav: \"audio/wav\",\n ogg: \"audio/ogg\",\n m4a: \"audio/mp4\",\n aac: \"audio/aac\",\n flac: \"audio/flac\",\n\n // Video\n mp4: \"video/mp4\",\n webm: \"video/webm\",\n avi: \"video/x-msvideo\",\n mov: \"video/quicktime\",\n wmv: \"video/x-ms-wmv\",\n flv: \"video/x-flv\",\n mkv: \"video/x-matroska\",\n\n // Office\n doc: \"application/msword\",\n docx: \"application/vnd.openxmlformats-officedocument.wordprocessingml.document\",\n xls: \"application/vnd.ms-excel\",\n xlsx: \"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet\",\n ppt: \"application/vnd.ms-powerpoint\",\n pptx: \"application/vnd.openxmlformats-officedocument.presentationml.presentation\",\n\n // Fonts\n woff: \"font/woff\",\n woff2: \"font/woff2\",\n ttf: \"font/ttf\",\n otf: \"font/otf\",\n eot: \"application/vnd.ms-fontobject\",\n };\n\n /**\n * Reverse MIME type map for looking up extensions from MIME types.\n * Prefers shorter, more common extensions when multiple exist.\n */\n protected static readonly reverseMimeMap: Record<string, string> = (() => {\n const reverse: Record<string, string> = {};\n // Process in order so common extensions come first\n for (const [ext, mimeType] of Object.entries(FileDetector.mimeMap)) {\n // Only set if not already set (prefer first/shorter extension)\n if (!reverse[mimeType]) {\n reverse[mimeType] = ext;\n }\n }\n return reverse;\n })();\n\n /**\n * Returns the file extension for a given MIME type.\n *\n * @param mimeType - The MIME type to look up\n * @returns The file extension (without dot), or \"bin\" if not found\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n * const ext = detector.getExtensionFromMimeType(\"image/png\"); // \"png\"\n * const ext2 = detector.getExtensionFromMimeType(\"application/octet-stream\"); // \"bin\"\n * ```\n */\n getExtensionFromMimeType(mimeType: string): string {\n return FileDetector.reverseMimeMap[mimeType] || \"bin\";\n }\n /**\n * Returns the content type of file based on its filename.\n *\n * @param filename - The filename to check\n * @returns The MIME type\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n * const mimeType = detector.getContentType(\"image.png\"); // \"image/png\"\n * ```\n */\n getContentType(filename: string): string {\n const ext = filename.toLowerCase().split(\".\").pop() || \"\";\n return FileDetector.mimeMap[ext] || \"application/octet-stream\";\n }\n\n /**\n * Detects the file type by checking magic bytes against the stream content.\n *\n * @param stream - The readable stream to check\n * @param filename - The filename (used to get the extension)\n * @returns File type information including MIME type, extension, and verification status\n *\n * @example\n * ```typescript\n * const detector = alepha.inject(FileDetector);\n * const stream = createReadStream('image.png');\n * const result = await detector.detectFileType(stream, 'image.png');\n * console.log(result.mimeType); // 'image/png'\n * console.log(result.verified); // true if magic bytes match\n * ```\n */\n async detectFileType(\n stream: Readable,\n filename: string,\n ): Promise<FileTypeResult> {\n // Get the expected MIME type from the filename extension\n const expectedMimeType = this.getContentType(filename);\n\n // Extract extension - only if filename contains a dot\n const lastDotIndex = filename.lastIndexOf(\".\");\n const ext =\n lastDotIndex > 0\n ? filename.substring(lastDotIndex + 1).toLowerCase()\n : \"\";\n\n // Read the first 16 bytes (enough for most magic byte checks)\n const { buffer, stream: newStream } = await this.peekBytes(stream, 16);\n\n // First, check if the extension's expected signature matches\n const expectedSignatures = FileDetector.MAGIC_BYTES[ext];\n if (expectedSignatures) {\n for (const { signature, mimeType } of expectedSignatures) {\n if (this.matchesSignature(buffer, signature)) {\n return {\n mimeType,\n extension: ext,\n verified: true,\n stream: newStream,\n };\n }\n }\n }\n\n // If the expected signature didn't match, try all other signatures\n for (const {\n ext: detectedExt,\n signature,\n mimeType,\n } of FileDetector.ALL_SIGNATURES) {\n if (detectedExt !== ext && this.matchesSignature(buffer, signature)) {\n return {\n mimeType,\n extension: detectedExt,\n verified: true,\n stream: newStream,\n };\n }\n }\n\n // If no magic bytes matched, fall back to extension-based detection\n // or return binary if extension is not recognized\n return {\n mimeType: expectedMimeType,\n extension: ext,\n verified: false,\n stream: newStream,\n };\n }\n\n /**\n * Reads all bytes from a stream and returns the first N bytes along with a new stream containing all data.\n * This approach reads the entire stream upfront to avoid complex async handling issues.\n *\n * @protected\n */\n protected async peekBytes(\n stream: Readable,\n numBytes: number,\n ): Promise<{ buffer: Buffer; stream: Readable }> {\n const chunks: Buffer[] = [];\n\n // Read the entire stream\n for await (const chunk of stream) {\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\n }\n\n const allData = Buffer.concat(chunks);\n const buffer = allData.subarray(0, numBytes);\n\n // Create a new stream with all the data\n const newStream = Readable.from(allData);\n\n return { buffer, stream: newStream };\n }\n\n /**\n * Checks if a buffer matches a magic byte signature.\n *\n * @protected\n */\n protected matchesSignature(\n buffer: Buffer,\n signature: (number | null)[],\n ): boolean {\n if (buffer.length < signature.length) {\n return false;\n }\n\n for (let i = 0; i < signature.length; i++) {\n if (signature[i] !== null && buffer[i] !== signature[i]) {\n return false;\n }\n }\n\n return true;\n }\n}\n","import { createReadStream } from \"node:fs\";\nimport {\n access,\n copyFile,\n cp as fsCp,\n mkdir as fsMkdir,\n readFile as fsReadFile,\n rm as fsRm,\n writeFile as fsWriteFile,\n readdir,\n rename,\n stat,\n} from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { PassThrough, Readable } from \"node:stream\";\nimport type { ReadableStream as NodeWebStream } from \"node:stream/web\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n $inject,\n AlephaError,\n type FileLike,\n isFileLike,\n type StreamLike,\n} from \"alepha\";\nimport { FileDetector } from \"../services/FileDetector.ts\";\nimport type {\n CpOptions,\n CreateFileOptions,\n FileSystemProvider,\n LsOptions,\n MkdirOptions,\n RmOptions,\n} from \"./FileSystemProvider.ts\";\n\n/**\n * Node.js implementation of FileSystem interface.\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Create from URL\n * const file1 = fs.createFile({ url: \"file:///path/to/file.png\" });\n *\n * // Create from Buffer\n * const file2 = fs.createFile({ buffer: Buffer.from(\"hello\"), name: \"hello.txt\" });\n *\n * // Create from text\n * const file3 = fs.createFile({ text: \"Hello, world!\", name: \"greeting.txt\" });\n *\n * // File operations\n * await fs.mkdir(\"/tmp/mydir\", { recursive: true });\n * await fs.cp(\"/src/file.txt\", \"/dest/file.txt\");\n * await fs.mv(\"/old/path.txt\", \"/new/path.txt\");\n * const files = await fs.ls(\"/tmp\");\n * await fs.rm(\"/tmp/file.txt\");\n * ```\n */\nexport class NodeFileSystemProvider implements FileSystemProvider {\n protected detector = $inject(FileDetector);\n\n public join(...paths: string[]): string {\n return join(...paths);\n }\n\n /**\n * Creates a FileLike object from various sources.\n *\n * @param options - Options for creating the file\n * @returns A FileLike object\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // From URL\n * const file1 = fs.createFile({ url: \"https://example.com/image.png\" });\n *\n * // From Buffer\n * const file2 = fs.createFile({\n * buffer: Buffer.from(\"hello\"),\n * name: \"hello.txt\",\n * type: \"text/plain\"\n * });\n *\n * // From text\n * const file3 = fs.createFile({ text: \"Hello!\", name: \"greeting.txt\" });\n *\n * // From stream with detection\n * const stream = createReadStream(\"/path/to/file.png\");\n * const file4 = fs.createFile({ stream, name: \"image.png\" });\n * ```\n */\n createFile(options: CreateFileOptions): FileLike {\n if (\"path\" in options) {\n const path = options.path;\n const filename = path.split(\"/\").pop() || \"file\";\n return this.createFileFromUrl(`file://${path}`, {\n type: options.type,\n name: options.name || filename,\n });\n }\n\n // Handle URL\n if (\"url\" in options) {\n return this.createFileFromUrl(options.url, {\n type: options.type,\n name: options.name,\n });\n }\n\n if (\"response\" in options) {\n if (!options.response.body) {\n throw new AlephaError(\"Response has no body stream\");\n }\n const res = options.response;\n // guess size from content-length header if available\n const sizeHeader = res.headers.get(\"content-length\");\n const size = sizeHeader ? parseInt(sizeHeader, 10) : undefined;\n // guess name from content-disposition header if available\n let name = options.name;\n const contentDisposition = res.headers.get(\"content-disposition\");\n if (contentDisposition && !name) {\n const match = contentDisposition.match(/filename=\"?([^\"]+)\"?/);\n if (match) {\n name = match[1];\n }\n }\n // guess type from content-type header if available\n const type = options.type || res.headers.get(\"content-type\") || undefined;\n return this.createFileFromStream(options.response.body, {\n type,\n name,\n size,\n });\n }\n\n // Handle Web File\n if (\"file\" in options) {\n return this.createFileFromWebFile(options.file, {\n type: options.type,\n name: options.name,\n size: options.size,\n });\n }\n\n // Handle Buffer\n if (\"buffer\" in options) {\n return this.createFileFromBuffer(options.buffer, {\n type: options.type,\n name: options.name,\n });\n }\n\n // Handle ArrayBuffer\n if (\"arrayBuffer\" in options) {\n return this.createFileFromBuffer(Buffer.from(options.arrayBuffer), {\n type: options.type,\n name: options.name,\n });\n }\n\n // Handle text\n if (\"text\" in options) {\n return this.createFileFromBuffer(Buffer.from(options.text, \"utf-8\"), {\n type: options.type || \"text/plain\",\n name: options.name || \"file.txt\",\n });\n }\n\n // Handle stream\n if (\"stream\" in options) {\n return this.createFileFromStream(options.stream, {\n type: options.type,\n name: options.name,\n size: options.size,\n });\n }\n\n throw new AlephaError(\n \"Invalid createFile options: no valid source provided\",\n );\n }\n\n /**\n * Removes a file or directory.\n *\n * @param path - The path to remove\n * @param options - Remove options\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Remove a file\n * await fs.rm(\"/tmp/file.txt\");\n *\n * // Remove a directory recursively\n * await fs.rm(\"/tmp/mydir\", { recursive: true });\n *\n * // Remove with force (no error if doesn't exist)\n * await fs.rm(\"/tmp/maybe-exists.txt\", { force: true });\n * ```\n */\n async rm(path: string, options?: RmOptions): Promise<void> {\n await fsRm(path, options);\n }\n\n /**\n * Copies a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n * @param options - Copy options\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Copy a file\n * await fs.cp(\"/src/file.txt\", \"/dest/file.txt\");\n *\n * // Copy a directory recursively\n * await fs.cp(\"/src/dir\", \"/dest/dir\", { recursive: true });\n *\n * // Copy with force (overwrite existing)\n * await fs.cp(\"/src/file.txt\", \"/dest/file.txt\", { force: true });\n * ```\n */\n async cp(src: string, dest: string, options?: CpOptions): Promise<void> {\n // Check if source is a directory\n const srcStat = await stat(src);\n\n if (srcStat.isDirectory()) {\n if (!options?.recursive) {\n throw new Error(\n `Cannot copy directory without recursive option: ${src}`,\n );\n }\n // Use Node.js cp function for recursive directory copy\n await fsCp(src, dest, {\n recursive: true,\n force: options?.force ?? false,\n });\n } else {\n // For files, use copyFile\n await copyFile(src, dest);\n }\n }\n\n /**\n * Moves/renames a file or directory.\n *\n * @param src - Source path\n * @param dest - Destination path\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Move/rename a file\n * await fs.mv(\"/old/path.txt\", \"/new/path.txt\");\n *\n * // Move a directory\n * await fs.mv(\"/old/dir\", \"/new/dir\");\n * ```\n */\n async mv(src: string, dest: string): Promise<void> {\n await rename(src, dest);\n }\n\n /**\n * Creates a directory.\n *\n * @param path - The directory path to create\n * @param options - Mkdir options\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Create a directory\n * await fs.mkdir(\"/tmp/mydir\");\n *\n * // Create nested directories\n * await fs.mkdir(\"/tmp/path/to/dir\", { recursive: true });\n *\n * // Create with specific permissions\n * await fs.mkdir(\"/tmp/mydir\", { mode: 0o755 });\n * ```\n */\n async mkdir(path: string, options?: MkdirOptions): Promise<void> {\n await fsMkdir(path, options);\n }\n\n /**\n * Lists files in a directory.\n *\n * @param path - The directory path to list\n * @param options - List options\n * @returns Array of filenames\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // List files in a directory\n * const files = await fs.ls(\"/tmp\");\n * console.log(files); // [\"file1.txt\", \"file2.txt\", \"subdir\"]\n *\n * // List with hidden files\n * const allFiles = await fs.ls(\"/tmp\", { hidden: true });\n *\n * // List recursively\n * const allFilesRecursive = await fs.ls(\"/tmp\", { recursive: true });\n * ```\n */\n async ls(path: string, options?: LsOptions): Promise<string[]> {\n const entries = await readdir(path);\n\n // Filter out hidden files if not requested\n const filteredEntries = options?.hidden\n ? entries\n : entries.filter((e) => !e.startsWith(\".\"));\n\n // If recursive, get all nested files\n if (options?.recursive) {\n const allFiles: string[] = [];\n\n for (const entry of filteredEntries) {\n const fullPath = join(path, entry);\n const entryStat = await stat(fullPath);\n\n if (entryStat.isDirectory()) {\n // Add directory entry\n allFiles.push(entry);\n // Recursively get files from subdirectory\n const subFiles = await this.ls(fullPath, options);\n allFiles.push(...subFiles.map((f) => join(entry, f)));\n } else {\n allFiles.push(entry);\n }\n }\n\n return allFiles;\n }\n\n return filteredEntries;\n }\n\n /**\n * Checks if a file or directory exists.\n *\n * @param path - The path to check\n * @returns True if the path exists, false otherwise\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * if (await fs.exists(\"/tmp/file.txt\")) {\n * console.log(\"File exists\");\n * }\n * ```\n */\n async exists(path: string): Promise<boolean> {\n try {\n await access(path);\n return true;\n } catch {\n return false;\n }\n }\n\n /**\n * Reads the content of a file.\n *\n * @param path - The file path to read\n * @returns The file content as a Buffer\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * const buffer = await fs.readFile(\"/tmp/file.txt\");\n * console.log(buffer.toString(\"utf-8\"));\n * ```\n */\n async readFile(path: string): Promise<Buffer> {\n return await fsReadFile(path);\n }\n\n /**\n * Writes data to a file.\n *\n * @param path - The file path to write to\n * @param data - The data to write (Buffer or string)\n *\n * @example\n * ```typescript\n * const fs = alepha.inject(NodeFileSystemProvider);\n *\n * // Write string\n * await fs.writeFile(\"/tmp/file.txt\", \"Hello, world!\");\n *\n * // Write Buffer\n * await fs.writeFile(\"/tmp/file.bin\", Buffer.from([0x01, 0x02, 0x03]));\n * ```\n */\n async writeFile(\n path: string,\n data: Uint8Array | Buffer | string | FileLike,\n ): Promise<void> {\n if (isFileLike(data)) {\n await fsWriteFile(path, Readable.from(data.stream()));\n return;\n }\n await fsWriteFile(path, data);\n }\n\n /**\n * Creates a FileLike object from a Web File.\n *\n * @protected\n */\n protected createFileFromWebFile(\n source: File,\n options: {\n type?: string;\n name?: string;\n size?: number;\n } = {},\n ): FileLike {\n const name = options.name ?? source.name;\n return {\n name,\n type: options.type ?? (source.type || this.detector.getContentType(name)),\n size: options.size ?? source.size ?? 0,\n lastModified: source.lastModified || Date.now(),\n stream: () => source.stream(),\n arrayBuffer: async (): Promise<ArrayBuffer> => {\n return await source.arrayBuffer();\n },\n text: async (): Promise<string> => {\n return await source.text();\n },\n };\n }\n\n /**\n * Creates a FileLike object from a Buffer.\n *\n * @protected\n */\n protected createFileFromBuffer(\n source: Buffer,\n options: {\n type?: string;\n name?: string;\n } = {},\n ): FileLike {\n const name: string = options.name ?? \"file\";\n return {\n name,\n type: options.type ?? this.detector.getContentType(options.name ?? name),\n size: source.byteLength,\n lastModified: Date.now(),\n stream: (): Readable => Readable.from(source),\n arrayBuffer: async (): Promise<ArrayBuffer> => {\n return this.bufferToArrayBuffer(source);\n },\n text: async (): Promise<string> => {\n return source.toString(\"utf-8\");\n },\n };\n }\n\n /**\n * Creates a FileLike object from a stream.\n *\n * @protected\n */\n protected createFileFromStream(\n source: StreamLike,\n options: {\n type?: string;\n name?: string;\n size?: number;\n } = {},\n ): FileLike & { _buffer: null | Buffer } {\n let buffer: Buffer | null = null;\n\n return {\n name: options.name ?? \"file\",\n type:\n options.type ?? this.detector.getContentType(options.name ?? \"file\"),\n size: options.size ?? 0,\n lastModified: Date.now(),\n stream: () => source,\n _buffer: null as Buffer | null,\n arrayBuffer: async () => {\n buffer ??= await this.streamToBuffer(source);\n return this.bufferToArrayBuffer(buffer);\n },\n text: async () => {\n buffer ??= await this.streamToBuffer(source);\n return buffer.toString(\"utf-8\");\n },\n };\n }\n\n /**\n * Creates a FileLike object from a URL.\n *\n * @protected\n */\n protected createFileFromUrl(\n url: string,\n options: {\n type?: string;\n name?: string;\n } = {},\n ): FileLike {\n const parsedUrl = new URL(url);\n const filename =\n options.name || parsedUrl.pathname.split(\"/\").pop() || \"file\";\n let buffer: Buffer | null = null;\n\n return {\n name: filename,\n type: options.type ?? this.detector.getContentType(filename),\n size: 0, // Unknown size until loaded\n lastModified: Date.now(),\n stream: () => this.createStreamFromUrl(url),\n arrayBuffer: async () => {\n buffer ??= await this.loadFromUrl(url);\n return this.bufferToArrayBuffer(buffer);\n },\n text: async () => {\n buffer ??= await this.loadFromUrl(url);\n return buffer.toString(\"utf-8\");\n },\n filepath: url,\n };\n }\n\n /**\n * Gets a streaming response from a URL.\n *\n * @protected\n */\n protected getStreamingResponse(url: string): Readable {\n const stream = new PassThrough();\n\n fetch(url)\n .then((res) =>\n Readable.fromWeb(res.body as unknown as NodeWebStream).pipe(stream),\n )\n .catch((err) => stream.destroy(err));\n\n return stream;\n }\n\n /**\n * Loads data from a URL.\n *\n * @protected\n */\n protected async loadFromUrl(url: string): Promise<Buffer> {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol === \"file:\") {\n // Handle file:// URLs\n const filePath = fileURLToPath(url);\n return await fsReadFile(filePath);\n } else if (\n parsedUrl.protocol === \"http:\" ||\n parsedUrl.protocol === \"https:\"\n ) {\n // Handle HTTP/HTTPS URLs\n const response = await fetch(url);\n if (!response.ok) {\n throw new Error(\n `Failed to fetch ${url}: ${response.status} ${response.statusText}`,\n );\n }\n const arrayBuffer = await response.arrayBuffer();\n return Buffer.from(arrayBuffer);\n } else {\n throw new Error(`Unsupported protocol: ${parsedUrl.protocol}`);\n }\n }\n\n /**\n * Creates a stream from a URL.\n *\n * @protected\n */\n protected createStreamFromUrl(url: string): Readable {\n const parsedUrl = new URL(url);\n\n if (parsedUrl.protocol === \"file:\") {\n // For file:// URLs, create a stream that reads the file\n return createReadStream(fileURLToPath(url));\n } else if (\n parsedUrl.protocol === \"http:\" ||\n parsedUrl.protocol === \"https:\"\n ) {\n // For HTTP/HTTPS URLs, create a stream that fetches the content\n return this.getStreamingResponse(url);\n } else {\n throw new AlephaError(`Unsupported protocol: ${parsedUrl.protocol}`);\n }\n }\n\n /**\n * Converts a stream-like object to a Buffer.\n *\n * @protected\n */\n protected async streamToBuffer(streamLike: StreamLike): Promise<Buffer> {\n const stream =\n streamLike instanceof Readable\n ? streamLike\n : Readable.fromWeb(streamLike as NodeWebStream);\n\n return new Promise<Buffer>((resolve, reject) => {\n const buffer: any[] = [];\n stream.on(\"data\", (chunk) => buffer.push(Buffer.from(chunk)));\n stream.on(\"end\", () => resolve(Buffer.concat(buffer)));\n stream.on(\"error\", (err) =>\n reject(new AlephaError(\"Error converting stream\", { cause: err })),\n );\n });\n }\n\n /**\n * Converts a Node.js Buffer to an ArrayBuffer.\n *\n * @protected\n */\n protected bufferToArrayBuffer(buffer: Buffer): ArrayBuffer {\n return buffer.buffer.slice(\n buffer.byteOffset,\n buffer.byteOffset + buffer.byteLength,\n ) as ArrayBuffer;\n }\n}\n","import { $module } from \"alepha\";\nimport { FileSystemProvider } from \"./providers/FileSystemProvider.ts\";\nimport { NodeFileSystemProvider } from \"./providers/NodeFileSystemProvider.ts\";\nimport { FileDetector } from \"./services/FileDetector.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./providers/FileSystemProvider.ts\";\nexport * from \"./providers/NodeFileSystemProvider.ts\";\nexport * from \"./services/FileDetector.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Provides file system capabilities for Alepha applications with support for multiple file sources and operations.\n *\n * The file module enables working with files from various sources (URLs, buffers, streams) and provides\n * utilities for file type detection, content type determination, and common file system operations.\n *\n * @see {@link FileDetector}\n * @see {@link FileSystemProvider}\n * @see {@link NodeFileSystemProvider}\n * @module alepha.file\n */\nexport const AlephaFile = $module({\n name: \"alepha.file\",\n primitives: [],\n services: [FileDetector, FileSystemProvider, NodeFileSystemProvider],\n register: (alepha) =>\n alepha.with({\n optional: true,\n provide: FileSystemProvider,\n use: NodeFileSystemProvider,\n }),\n});\n"],"mappings":"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AM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAa,CAAC;EACrE,MAAM,CAAC;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,CAAC;EAGvE,KAAK;GACH;IACE,WAAW;KAAC;KAAM;KAAM;KAAM;KAAM;KAAM;KAAM;KAAM;KAAK;IAC3D,UAAU;IACX;GACD;IACE,WAAW;KACT;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD;IACD,UAAU;IACX;GACD;IACE,WAAW;KACT;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACA;KACD;IACD,UAAU;IACX;GACF;EACD,MAAM,CAAC;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAc,CAAC;EACvE,KAAK,CACH;GACE,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACD,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IACT;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACD;GACD,UAAU;GACX,CACF;EACD,KAAK,CACH;GAAE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GAAE,UAAU;GAAoB,CACtE;EAGD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GACnC,UACE;GACH,CACF;EACD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GACnC,UACE;GACH,CACF;EACD,MAAM,CACJ;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAK;GACnC,UACE;GACH,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC3D,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAM;IAAK;GAC3D,UAAU;GACX,CACF;EACD,KAAK,CACH;GACE,WAAW;IAAC;IAAM;IAAM;IAAM;IAAM;I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"}
|
package/dist/logger/index.d.ts
CHANGED
|
@@ -257,7 +257,7 @@ declare const envSchema: alepha6.TObject<{
|
|
|
257
257
|
* Built-in log formats.
|
|
258
258
|
* - "json" - JSON format, useful for structured logging and log aggregation. {@link JsonFormatterProvider}
|
|
259
259
|
* - "pretty" - Simple text format, human-readable, with colors. {@link PrettyFormatterProvider}
|
|
260
|
-
* - "raw" - Raw format, no formatting, just the message.
|
|
260
|
+
* - "raw" - Raw format, no formatting, just the message. {@link RawFormatterProvider}
|
|
261
261
|
*/
|
|
262
262
|
LOG_FORMAT: alepha6.TOptional<alepha6.TUnsafe<"json" | "pretty" | "raw">>;
|
|
263
263
|
}>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/logger/schemas/logEntrySchema.ts","../../src/logger/providers/LogDestinationProvider.ts","../../src/logger/providers/LogFormatterProvider.ts","../../src/logger/services/Logger.ts","../../src/logger/primitives/$logger.ts","../../src/logger/providers/ConsoleColorProvider.ts","../../src/logger/providers/ConsoleDestinationProvider.ts","../../src/logger/providers/JsonFormatterProvider.ts","../../src/logger/providers/MemoryDestinationProvider.ts","../../src/logger/providers/PrettyFormatterProvider.ts","../../src/logger/index.ts"],"sourcesContent":[],"mappings":";;;;;cAEa,wBAAc;SAWzB,OAAA,CAAA;;;EAXW,MAAA,iBAWX;EAAA,OAAA,mBAAA,iBAAA;;;;;KAEU,QAAA,GAAW,cAAc;;;uBCbf,sBAAA;yCAC0B;;;;uBCD1B,oBAAA;yBACU;;;;AFDnB,cGUA,MAAA,YAAkB,eHC7B,CAAA;EAAA,mBAAA,MAAA,EGAyB,MHAzB;gCGC4B;kCACE;uCACK;6BAER;;;;;sBAcP;;aH9BK,CAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,IAAA,KAAA,CAAA,CAAA,EAAA,MAAA;EAaf,UAAA,CAAQ,KAAA,EAAA,MAAiB,EAAA,GAAA,EAAA,MAAA,CAAd,EGsC0B,QHtCpB;;iCG6FW;;EF1GlB,IAAA,CAAA,OAAA,EAAA,MAAA,EAAA,IAAsB,CAAA,EAAA,OAAA,CACI,EAAA,IAAA;;;;ECD1B,UAAA,GAAA,CAAA,KAAA,ECyIC,QDzImB,EAAA,OACV,EAAA,MAAQ,EAAA,IAAA,CAAA,EAAA,OAAA,CAAA,EAAA,IAAA;wBC8KhB;;;;;;;AH/KxB;;;;;;;;;;;;;;AAaA;;cIOa;aAAoB,yBAA8B;EHpBzC,MAAA,EAAA,aAAA;;UGgCL,sBAAA;;AFhCjB;;;cGYa,oBAAA;;;;ILZA,GAAA,EAAA,MAAA;IAWX,KAAA,EAAA,MAAA;;;;;;;;;;;UAXyB,EAAA,MAAA;IAAA,KAAA,EAAA,MAAA;IAaf,IAAA,EAAA,MAAQ;;;;ECbE,CAAA;;;;ECAA,CAAA;6BGsCK;;;EF5Bd,SAAO,CAAA,CAAA,EAAA,OAAA;EACO,GAAA,CAAA,KAAA,EAAA,MAAA,OEgDH,oBAAA,CAAqB,MFhDlB,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;cGXd,0BAAA,SAAmC,sBAAA;;;;;cCCnC,qBAAA,SAA8B,oBAAA;gBACpB;yBAoBS;APtBhC;;;cQCa,yBAAA,SAAkC,sBAAA;qBAC1B,MAAM;;ERFd,CAAA,CAAA;EAWX,SAAA,OAAA,EAAA;;;kCQHuC;;;;;;;;URRd,EAAA,MAAA;IAAA,SAAA,EAAA,MAAA;EAaf,CAAA,GAAA;;;;ACbZ;;;cQGa,uBAAA,SAAgC,oBAAA;ETHhC,UAAA,KAAA,ESII,oBTOf;EAAA,UAAA,MAAA,ESNgB,MTMhB;gBSJqB;;;;;;;;+BAyFQ;;;;;;;;;;;ATnF/B;;;;ACbA;;;;ACAA;;;;ACUA;;;;;;;;;;;;;;;;ACUA;;;;;;AAYA;;;;ACpBA;;;;ACZA;;;;ACCA;;;;;;;;ACAA;;;;;;;cE6Fa,cAAY,OAAA,CAAA,QAoFvB,OAAA,CApFuB,MAAA;cAwFnB,mBAAS;EDnLF;;;;;;;;;;AC2Fb;AAoFG;;;;;WAIY,mBAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/logger/schemas/logEntrySchema.ts","../../src/logger/providers/LogDestinationProvider.ts","../../src/logger/providers/LogFormatterProvider.ts","../../src/logger/services/Logger.ts","../../src/logger/primitives/$logger.ts","../../src/logger/providers/ConsoleColorProvider.ts","../../src/logger/providers/ConsoleDestinationProvider.ts","../../src/logger/providers/JsonFormatterProvider.ts","../../src/logger/providers/MemoryDestinationProvider.ts","../../src/logger/providers/PrettyFormatterProvider.ts","../../src/logger/index.ts"],"sourcesContent":[],"mappings":";;;;;cAEa,wBAAc;SAWzB,OAAA,CAAA;;;EAXW,MAAA,iBAWX;EAAA,OAAA,mBAAA,iBAAA;;;;;KAEU,QAAA,GAAW,cAAc;;;uBCbf,sBAAA;yCAC0B;;;;uBCD1B,oBAAA;yBACU;;;;AFDnB,cGUA,MAAA,YAAkB,eHC7B,CAAA;EAAA,mBAAA,MAAA,EGAyB,MHAzB;gCGC4B;kCACE;uCACK;6BAER;;;;;sBAcP;;aH9BK,CAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAAA,IAAA,KAAA,CAAA,CAAA,EAAA,MAAA;EAaf,UAAA,CAAQ,KAAA,EAAA,MAAiB,EAAA,GAAA,EAAA,MAAA,CAAd,EGsC0B,QHtCpB;;iCG6FW;;EF1GlB,IAAA,CAAA,OAAA,EAAA,MAAA,EAAA,IAAsB,CAAA,EAAA,OAAA,CACI,EAAA,IAAA;;;;ECD1B,UAAA,GAAA,CAAA,KAAA,ECyIC,QDzImB,EAAA,OACV,EAAA,MAAQ,EAAA,IAAA,CAAA,EAAA,OAAA,CAAA,EAAA,IAAA;wBC8KhB;;;;;;;AH/KxB;;;;;;;;;;;;;;AAaA;;cIOa;aAAoB,yBAA8B;EHpBzC,MAAA,EAAA,aAAA;;UGgCL,sBAAA;;AFhCjB;;;cGYa,oBAAA;;;;ILZA,GAAA,EAAA,MAAA;IAWX,KAAA,EAAA,MAAA;;;;;;;;;;;UAXyB,EAAA,MAAA;IAAA,KAAA,EAAA,MAAA;IAaf,IAAA,EAAA,MAAQ;;;;ECbE,CAAA;;;;ECAA,CAAA;6BGsCK;;;EF5Bd,SAAO,CAAA,CAAA,EAAA,OAAA;EACO,GAAA,CAAA,KAAA,EAAA,MAAA,OEgDH,oBAAA,CAAqB,MFhDlB,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,CAAA,EAAA,MAAA,CAAA,EAAA,MAAA;;;;cGXd,0BAAA,SAAmC,sBAAA;;;;;cCCnC,qBAAA,SAA8B,oBAAA;gBACpB;yBAoBS;APtBhC;;;cQCa,yBAAA,SAAkC,sBAAA;qBAC1B,MAAM;;ERFd,CAAA,CAAA;EAWX,SAAA,OAAA,EAAA;;;kCQHuC;;;;;;;;URRd,EAAA,MAAA;IAAA,SAAA,EAAA,MAAA;EAaf,CAAA,GAAA;;;;ACbZ;;;cQGa,uBAAA,SAAgC,oBAAA;ETHhC,UAAA,KAAA,ESII,oBTOf;EAAA,UAAA,MAAA,ESNgB,MTMhB;gBSJqB;;;;;;;;+BAyFQ;;;;;;;;;;;ATnF/B;;;;ACbA;;;;ACAA;;;;ACUA;;;;;;;;;;;;;;;;ACUA;;;;;;AAYA;;;;ACpBA;;;;ACZA;;;;ACCA;;;;;;;;ACAA;;;;;;;cE6Fa,cAAY,OAAA,CAAA,QAoFvB,OAAA,CApFuB,MAAA;cAwFnB,mBAAS;EDnLF;;;;;;;;;;AC2Fb;AAoFG;;;;;WAIY,mBAAA,CAwCb,OAAA,CAAA,OAAA,CAxCa;EAAA;AAAA;;;;;EA6CgB,UAAA,mBAAA,gBAAA,CAAA,MAAA,GAAA,QAAA,GAAA,KAAA,CAAA,CAAA;EAYlB;eAAQ,QAAA,CAAA;EAAA,UAAA,GAAA,SAZU,OAYV,CAZkB,MAYlB,CAAA,OAZgC,SAYhC,CAAA,CAAA,CAAA,CAAA;;;;;;;;;;aAAR"}
|
package/dist/logger/index.js
CHANGED
|
@@ -503,12 +503,22 @@ const AlephaLogger = $module({
|
|
|
503
503
|
}
|
|
504
504
|
});
|
|
505
505
|
const envSchema = t.object({
|
|
506
|
-
LOG_LEVEL: t.optional(t.text({
|
|
506
|
+
LOG_LEVEL: t.optional(t.text({
|
|
507
|
+
description: `Application log level on startup.
|
|
508
|
+
Levels are: trace, debug, info, warn, error, silent
|
|
509
|
+
Level can be set for a specific module:
|
|
510
|
+
"my.module.name:debug,info" -> Set debug level for my.module.name and info for all other modules
|
|
511
|
+
"alepha:trace,info" -> Set trace level for all alepha modules and info for all other modules`,
|
|
512
|
+
lowercase: true
|
|
513
|
+
})),
|
|
507
514
|
LOG_FORMAT: t.optional(t.enum([
|
|
508
515
|
"json",
|
|
509
516
|
"pretty",
|
|
510
517
|
"raw"
|
|
511
|
-
], {
|
|
518
|
+
], {
|
|
519
|
+
description: "Default log format for the application.",
|
|
520
|
+
lowercase: true
|
|
521
|
+
}))
|
|
512
522
|
});
|
|
513
523
|
|
|
514
524
|
//#endregion
|
package/dist/logger/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["envSchema"],"sources":["../../src/logger/providers/LogDestinationProvider.ts","../../src/logger/providers/LogFormatterProvider.ts","../../src/logger/services/Logger.ts","../../src/logger/primitives/$logger.ts","../../src/logger/providers/ConsoleColorProvider.ts","../../src/logger/providers/ConsoleDestinationProvider.ts","../../src/logger/providers/JsonFormatterProvider.ts","../../src/logger/providers/MemoryDestinationProvider.ts","../../src/logger/providers/PrettyFormatterProvider.ts","../../src/logger/providers/RawFormatterProvider.ts","../../src/logger/schemas/logEntrySchema.ts","../../src/logger/index.ts"],"sourcesContent":["import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\n\nexport abstract class LogDestinationProvider {\n public abstract write(message: string, entry: LogEntry): void;\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\n\nexport abstract class LogFormatterProvider {\n public abstract format(entry: LogEntry): string;\n}\n","import {\n $inject,\n Alepha,\n AlephaError,\n type LoggerInterface,\n type LogLevel,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { LogDestinationProvider } from \"../providers/LogDestinationProvider.ts\";\nimport { LogFormatterProvider } from \"../providers/LogFormatterProvider.ts\";\nimport type { LogEntry } from \"../schemas/logEntrySchema.ts\";\n\nexport class Logger implements LoggerInterface {\n protected readonly alepha = $inject(Alepha);\n protected readonly formatter = $inject(LogFormatterProvider);\n protected readonly destination = $inject(LogDestinationProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n protected readonly levels: Record<string, number> = {\n SILENT: -1,\n ERROR: 0,\n WARN: 1,\n INFO: 2,\n DEBUG: 3,\n TRACE: 4,\n };\n\n protected readonly service: string;\n protected readonly module: string;\n protected readonly app?: string;\n\n protected appLogLevel: string = \"INFO\";\n protected logLevel: LogLevel = \"INFO\";\n\n constructor(service: string, module: string) {\n this.service = service;\n this.module = module;\n this.app = this.alepha.env.APP_NAME;\n }\n\n public get context(): string | undefined {\n return this.alepha.context.get<string>(\"context\");\n }\n\n public get level(): string {\n const stateLogLevel = this.alepha.store.get(\"alepha.logger.level\");\n if (stateLogLevel && stateLogLevel !== this.appLogLevel) {\n this.appLogLevel = stateLogLevel;\n this.logLevel = this.parseLevel(this.appLogLevel, this.module);\n }\n return this.logLevel;\n }\n\n public parseLevel(level: string, app: string): LogLevel {\n const parts = level.toLowerCase().split(/[,;]/);\n\n // First pass: check for module-specific configurations\n for (const part of parts) {\n const trimmedPart = part.trim();\n if (!trimmedPart) continue; // Skip empty parts\n\n if (trimmedPart.includes(\":\") || trimmedPart.includes(\"=\")) {\n const [modulePattern, levelValue] = trimmedPart.split(/[:=]/);\n const trimmedModule = modulePattern.trim();\n const trimmedLevel = levelValue?.trim();\n\n if (!trimmedLevel) continue; // Skip if no level specified\n\n if (this.matchesPattern(app, trimmedModule)) {\n try {\n return this.asLogLevel(trimmedLevel);\n } catch (error) {\n throw new AlephaError(\n `Invalid log level '${levelValue?.trim()}' for module pattern '${trimmedModule}'`,\n );\n }\n }\n }\n }\n\n // Second pass: look for global level\n for (const part of parts) {\n const trimmedPart = part.trim();\n if (!trimmedPart) continue; // Skip empty parts\n\n if (!trimmedPart.includes(\":\") && !trimmedPart.includes(\"=\")) {\n try {\n return this.asLogLevel(trimmedPart);\n } catch (error) {\n throw new Error(`Invalid global log level \"${trimmedPart}\"`);\n }\n }\n }\n\n return \"INFO\";\n }\n\n private matchesPattern(moduleName: string, pattern: string): boolean {\n if (pattern.includes(\"*\")) {\n // Convert wildcard pattern to regex\n const regexPattern = pattern.replace(/\\./g, \"\\\\.\").replace(/\\*/g, \".*\");\n return new RegExp(`^${regexPattern}`).test(moduleName);\n }\n\n // Exact prefix match (existing behavior)\n return moduleName.startsWith(pattern);\n }\n\n public asLogLevel(something: string): LogLevel {\n const level = something.trim().toUpperCase();\n if (this.levels[level] !== undefined) {\n return level as LogLevel;\n }\n\n throw new AlephaError(`Invalid log level: ${something}`);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n public error(message: string, data?: unknown): void {\n this.log(\"ERROR\", message, data);\n }\n\n public warn(message: string, data?: unknown): void {\n this.log(\"WARN\", message, data);\n }\n\n public info(message: string, data?: unknown): void {\n this.log(\"INFO\", message, data);\n }\n\n public debug(message: string, data?: unknown): void {\n this.log(\"DEBUG\", message, data);\n }\n\n public trace(message: string, data?: unknown): void {\n this.log(\"TRACE\", message, data);\n }\n\n protected log(level: LogLevel, message: string, data?: unknown): void {\n let _message = \"\";\n if (typeof message === \"string\") {\n _message = message;\n } else if (typeof data === \"string\") {\n _message = data;\n }\n\n let _data: object | Error | undefined;\n if (typeof data === \"object\" && !!data) {\n _data = data;\n } else if (typeof message === \"object\" && message) {\n _data = message;\n }\n\n const logEntry: LogEntry = {\n level,\n message: _message,\n data: _data,\n context: this.context,\n service: this.service,\n module: this.module,\n app: this.app,\n timestamp: this.dateTimeProvider.nowMillis(),\n };\n\n if (this.levels[level] > this.levels[this.level]) {\n this.emit(logEntry);\n return;\n }\n\n const formatted = this.formatter.format(logEntry);\n\n this.emit(logEntry, formatted);\n\n this.destination.write(formatted, logEntry);\n }\n\n protected emit(entry: LogEntry, message?: string) {\n this.alepha.events\n .emit(\n \"log\",\n {\n message,\n entry,\n },\n {\n catch: true,\n },\n )\n .catch(() => null);\n }\n}\n","import { $context, $inject, KIND } from \"alepha\";\nimport { Logger } from \"../services/Logger.ts\";\n\n/**\n * Create a logger.\n *\n * `name` is optional, by default it will use the name of the service.\n *\n * @example\n * ```ts\n * import { $logger } from \"alepha\";\n *\n * class MyService {\n * \tlog = $logger();\n *\n * constructor() {\n * this.log.info(\"Service initialized\");\n * // print something like '[23:45:53.326] INFO <app.MyService>: Service initialized'\n * }\n * }\n * ```\n */\nexport const $logger = (options: LoggerPrimitiveOptions = {}): Logger => {\n const { alepha, service, module } = $context();\n\n return $inject(Logger, {\n lifetime: \"transient\",\n args: [\n options.name ?? service?.name ?? \"Func\",\n module?.name ?? alepha.env.MODULE_NAME ?? \"app\",\n ],\n });\n};\n\nexport interface LoggerPrimitiveOptions {\n name?: string;\n}\n\n$logger[KIND] = Logger;\n","import { $env, $inject, Alepha, t } from \"alepha\";\n\nconst envSchema = t.object({\n /**\n * Disable colors in the console output.\n */\n NO_COLOR: t.optional(t.text()),\n\n /**\n * Force color output for the application.\n */\n FORCE_COLOR: t.optional(t.text()),\n});\n\nexport class ConsoleColorProvider {\n static readonly COLORS = {\n RESET: \"\\x1b[0m\",\n BLACK: \"\\x1b[30m\",\n RED: \"\\x1b[31m\",\n GREEN: \"\\x1b[32m\",\n ORANGE: \"\\x1b[33m\", // using yellow for orange-ish\n BLUE: \"\\x1b[34m\",\n PURPLE: \"\\x1b[35m\",\n CYAN: \"\\x1b[36m\",\n GREY_LIGHT: \"\\x1b[37m\",\n GREY_LIGHT_BOLD: \"\\x1b[1;37m\",\n GREY_DARK: \"\\x1b[90m\",\n GREY_DARK_BOLD: \"\\x1b[1;90m\",\n WHITE: \"\\x1b[97m\",\n WHITE_BOLD: \"\\x1b[1;97m\",\n // levels\n SILENT: \"\",\n ERROR: \"\\x1b[31m\",\n WARN: \"\\x1b[33m\",\n INFO: \"\\x1b[32m\",\n DEBUG: \"\\x1b[34m\",\n TRACE: \"\\x1b[90m\",\n };\n\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n\n protected enabled = true;\n\n constructor() {\n this.enabled = this.isEnabled();\n }\n\n public isEnabled(): boolean {\n if (this.env.NO_COLOR) {\n return false;\n }\n\n if (this.env.FORCE_COLOR) {\n return true;\n }\n\n return !this.alepha.isProduction();\n }\n\n public set(\n color: keyof typeof ConsoleColorProvider.COLORS,\n text: string,\n reset: string = ConsoleColorProvider.COLORS.RESET,\n ): string {\n if (!this.enabled) {\n return text;\n }\n\n return `${ConsoleColorProvider.COLORS[color]}${text}${reset}`;\n }\n}\n","import { LogDestinationProvider } from \"./LogDestinationProvider.ts\";\n\nexport class ConsoleDestinationProvider extends LogDestinationProvider {\n public write(message: string): void {\n console.log(message);\n }\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { LogFormatterProvider } from \"./LogFormatterProvider.ts\";\n\nexport class JsonFormatterProvider extends LogFormatterProvider {\n public format(entry: LogEntry): string {\n const json: Record<string, any> = {\n level: entry.level,\n message: entry.message,\n context: entry.context,\n service: entry.service,\n module: entry.module,\n app: entry.app,\n time: entry.timestamp,\n };\n\n if (entry.data instanceof Error) {\n json.error = this.formatJsonError(entry.data);\n } else {\n json.data = entry.data;\n }\n\n return JSON.stringify(json);\n }\n\n public formatJsonError(error: Error): object {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n cause:\n error.cause instanceof Error\n ? this.formatJsonError(error.cause)\n : undefined,\n };\n }\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { LogDestinationProvider } from \"./LogDestinationProvider.ts\";\n\nexport class MemoryDestinationProvider extends LogDestinationProvider {\n protected entries: Array<LogEntry & { formatted: string }> = [];\n\n public readonly options = {\n maxEntries: 1000,\n };\n\n public write(formatted: string, entry: LogEntry): void {\n this.entries.push({ ...entry, formatted });\n\n if (this.entries.length > this.options.maxEntries) {\n this.entries = this.entries.slice(\n -Math.floor(this.options.maxEntries * 0.8),\n );\n }\n }\n\n public get logs() {\n return [...this.entries];\n }\n\n public clear(): void {\n this.entries = [];\n }\n}\n","import { $inject, Alepha } from \"alepha\";\nimport type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { ConsoleColorProvider } from \"./ConsoleColorProvider.ts\";\nimport { LogFormatterProvider } from \"./LogFormatterProvider.ts\";\n\nexport class PrettyFormatterProvider extends LogFormatterProvider {\n protected color = $inject(ConsoleColorProvider);\n protected alepha = $inject(Alepha);\n\n public format(entry: LogEntry): string {\n const { data, timestamp } = entry;\n\n let output = \"\";\n let details = \"\";\n\n const isError = data instanceof Error;\n if (isError) {\n details = this.formatError(data);\n } else if (data) {\n try {\n details = JSON.stringify(data);\n } catch {\n details = \"[Unserializable Object]\";\n }\n }\n\n output += this.color.set(\n \"GREY_DARK\",\n `[${this.formatTimestamp(timestamp)}]`,\n );\n output += \" \";\n\n output += this.color.set(entry.level, entry.level.toUpperCase());\n output += \" \";\n\n if (entry.app) {\n output += this.color.set(\"GREY_DARK\", `${entry.app}`);\n output += \" \";\n }\n\n if (entry.context) {\n output += this.color.set(\n \"GREY_DARK\",\n `(${this.formatContext(entry.context)})`,\n );\n output += \" \";\n }\n\n const module = this.color.set(\"GREY_LIGHT\", `${entry.module}.`);\n const service = this.color.set(\n this.alepha.isBrowser() ? \"RESET\" : \"WHITE\",\n entry.service,\n );\n\n output += `<${module}${service}>`;\n\n if (entry.message) {\n output += `: ${this.color.set(\"CYAN\", entry.message)}`;\n } else {\n output += \":\";\n }\n\n if (details) {\n if (isError) {\n output += ` \\n${details}`;\n } else {\n output += ` ${this.color.set(\"GREY_DARK\", details)}`;\n }\n }\n\n return output;\n }\n\n public formatTimestamp(timestamp: number): string {\n const d = new Date(timestamp);\n const h = d.getHours();\n const m = d.getMinutes();\n const s = d.getSeconds();\n const ms = d.getMilliseconds();\n\n return `${this.pad2(h)}:${this.pad2(m)}:${this.pad2(s)}.${this.pad3(ms)}`;\n }\n\n protected pad2 = (n: number) => (n < 10 ? \"0\" : \"\") + n;\n protected pad3 = (n: number) =>\n n < 10 ? `00${n}` : n < 100 ? `0${n}` : `${n}`;\n\n /**\n * Avoid to display the whole UUID in development mode\n */\n protected formatContext(context: string): string {\n if (this.alepha.isProduction()) {\n return context;\n }\n\n return context.slice(0, 8);\n }\n\n protected formatError(error: Error): string {\n // Chrome does not like stack traces with ASCII colors\n // so we remove the stack trace from log and just print with console.error\n if (this.alepha.isBrowser()) {\n // call console.error in a separate tick to avoid messing with log order\n setTimeout(() => {\n console.error(error);\n });\n return \"\";\n }\n\n if (this.alepha.isViteDev()) {\n // Node.js - try to fix stack trace with Vite SSR helper\n // Actually, it works only because we have a global helper in viteAlephaDev.ts\n const gl = globalThis as Record<string, unknown>;\n if (typeof gl === \"object\" && typeof gl.ssrFixStacktrace === \"function\") {\n gl.ssrFixStacktrace(error);\n }\n }\n\n let str = error.stack ?? error.message;\n\n const anyError = error as any;\n while (anyError.cause && anyError.cause instanceof Error) {\n str += `\\nCaused by: ${anyError.cause.stack ?? anyError.cause.message}`;\n anyError.cause = anyError.cause.cause;\n }\n\n return str;\n }\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { LogFormatterProvider } from \"./LogFormatterProvider.ts\";\n\nexport class RawFormatterProvider extends LogFormatterProvider {\n public format(entry: LogEntry): string {\n let output = \"\";\n\n output += `${entry.message}`;\n\n if (entry.data instanceof Error) {\n output += `\\n${entry.data.message}`;\n let cause = entry.data.cause;\n while (cause instanceof Error) {\n output += `\\nCaused by: ${cause.message}`;\n cause = cause.cause;\n }\n }\n\n return output;\n }\n}\n","import { type Static, t } from \"alepha\";\n\nexport const logEntrySchema = t.object({\n level: t.enum([\"SILENT\", \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\"]),\n message: t.text({\n size: \"rich\",\n }),\n service: t.text(),\n module: t.text(),\n context: t.optional(t.text()),\n app: t.optional(t.text()),\n data: t.optional(t.any()),\n timestamp: t.number(),\n});\n\nexport type LogEntry = Static<typeof logEntrySchema>;\n","import { $module, type Static, t } from \"alepha\";\nimport { $logger } from \"./primitives/$logger.ts\";\nimport { ConsoleColorProvider } from \"./providers/ConsoleColorProvider.ts\";\nimport { ConsoleDestinationProvider } from \"./providers/ConsoleDestinationProvider.ts\";\nimport { JsonFormatterProvider } from \"./providers/JsonFormatterProvider.ts\";\nimport { LogDestinationProvider } from \"./providers/LogDestinationProvider.ts\";\nimport { LogFormatterProvider } from \"./providers/LogFormatterProvider.ts\";\nimport { MemoryDestinationProvider } from \"./providers/MemoryDestinationProvider.ts\";\nimport { PrettyFormatterProvider } from \"./providers/PrettyFormatterProvider.ts\";\nimport { RawFormatterProvider } from \"./providers/RawFormatterProvider.ts\";\nimport type { LogEntry } from \"./schemas/logEntrySchema.ts\";\nimport { Logger } from \"./services/Logger.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$logger.ts\";\nexport * from \"./providers/ConsoleColorProvider.ts\";\nexport * from \"./providers/ConsoleDestinationProvider.ts\";\nexport * from \"./providers/JsonFormatterProvider.ts\";\nexport * from \"./providers/LogDestinationProvider.ts\";\nexport * from \"./providers/LogFormatterProvider.ts\";\nexport * from \"./providers/MemoryDestinationProvider.ts\";\nexport * from \"./providers/PrettyFormatterProvider.ts\";\nexport * from \"./schemas/logEntrySchema.ts\";\nexport * from \"./services/Logger.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Minimalist logger module for Alepha.\n *\n * It offers a global logger interface (info, warn, ...) via the `$logger` primitive.\n *\n * ```ts\n * import { $logger } from \"alepha/logger\";\n *\n * class App {\n * log = $logger();\n * }\n * ```\n *\n * ### Formatting and Destinations\n *\n * `AlephaLogger` is **extensible**, destinations and formatters can be added or replaced.\n *\n * Default log destinations are:\n * - ConsoleDestinationProvider: logs to the console.\n * - MemoryDestinationProvider: stores logs in memory for later retrieval.\n *\n * Default log formatters are:\n * - JsonFormatterProvider: formats logs as JSON.\n * - SimpleFormatterProvider: formats logs as simple text (with colors when possible).\n * - RawFormatterProvider: formats logs as raw text without any formatting.\n *\n * ### Event Emission\n *\n * The logger emits 'log' events that can be listened to by external code, allowing for custom log processing and destinations.\n *\n * ```ts\n * class CustomDestination {\n * onLog = $hook({\n * on: \"log\",\n * handler: (ev) => {\n * // ev.message (formatted message)\n * // ev.entry (level, raw message, ...)\n * }\n * });\n * }\n * ```\n *\n * ### Log Level\n *\n * You can configure the log level and format via environment variables:\n *\n * - `LOG_LEVEL`: Sets the default log level for the application.\n * - `LOG_FORMAT`: Sets the default log format for the application.\n *\n * ```bash\n * LOG_LEVEL=debug LOG_FORMAT=json node src/index.ts\n * ```\n *\n * Log level is also available in the state as `logLevel`, which can be used to dynamically change the log level at runtime.\n * ```ts\n * alepha.state.set(\"alepha.logger.level\", \"debug\");\n * ```\n *\n * Log level is $module aware, meaning you can set different log levels for different modules.\n *\n * **Module-specific configuration:**\n * - `LOG_LEVEL=my.module.name:debug,info` - debug for `my.module.name` (and submodules), info for others\n * - `LOG_LEVEL=alepha:trace,my.app:error,info` - trace for alepha modules, error for my.app modules, info for others\n *\n * **Wildcard patterns (NEW):**\n * - `LOG_LEVEL=alepha.*:debug,info` - debug for all alepha submodules\n * - `LOG_LEVEL=*.test:silent,*.core:trace,info` - silent for test modules, trace for core modules\n */\nexport const AlephaLogger = $module({\n name: \"alepha.logger\",\n primitives: [$logger],\n services: [\n Logger,\n ConsoleDestinationProvider,\n MemoryDestinationProvider,\n JsonFormatterProvider,\n PrettyFormatterProvider,\n RawFormatterProvider,\n ConsoleColorProvider,\n ],\n register: (alepha) => {\n const env = alepha.parseEnv(envSchema);\n\n const getLogDestinationProvider = () => {\n // in test mode, if no LOG_LEVEL is set, use MemoryDestinationProvider to capture logs for inspection.\n // logs will be printed to console only if the test fails.\n if (alepha.isTest() && !env.LOG_LEVEL) {\n const printOnError = (ev: any) => {\n if (ev.task?.result?.state === \"fail\") {\n const output = alepha.inject(MemoryDestinationProvider);\n for (const log of output.logs) {\n console.log(log.formatted);\n }\n }\n };\n\n try {\n alepha.store.get(\"alepha.test.afterEach\")?.(printOnError);\n alepha.store.get(\"alepha.test.onTestFinished\")?.(printOnError);\n } catch {\n // ignore\n }\n\n return MemoryDestinationProvider;\n }\n\n return ConsoleDestinationProvider;\n };\n\n const getLogFormatterProvider = () => {\n if (env.LOG_FORMAT) {\n if (env.LOG_FORMAT === \"json\") {\n return JsonFormatterProvider;\n }\n if (env.LOG_FORMAT === \"raw\") {\n return RawFormatterProvider;\n }\n return PrettyFormatterProvider;\n }\n\n if (alepha.isProduction() && !alepha.isBrowser()) {\n return JsonFormatterProvider;\n }\n\n return PrettyFormatterProvider;\n };\n\n alepha.with({\n optional: true,\n provide: LogDestinationProvider,\n use: getLogDestinationProvider(),\n });\n\n alepha.with({\n optional: true,\n provide: LogFormatterProvider,\n use: getLogFormatterProvider(),\n });\n\n alepha.store.set(\n \"alepha.logger\",\n alepha.inject(Logger, {\n lifetime: \"transient\",\n args: [\"Alepha\", \"alepha.core\"],\n }),\n );\n\n alepha.store.set(\n \"alepha.logger.level\",\n env.LOG_LEVEL ?? (alepha.isTest() ? \"trace\" : \"info\"),\n );\n },\n});\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n /**\n * Default log level for the application.\n *\n * Default by environment:\n * - dev = info\n * - prod = info\n * - test = error\n *\n * Levels are: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\"\n *\n * Level can be set for a specific module:\n *\n * @example\n * LOG_LEVEL=my.module.name:debug,info # Set debug level for my.module.name and info for all other modules\n * LOG_LEVEL=alepha:trace, info # Set trace level for all alepha modules and info for all other modules\n */\n LOG_LEVEL: t.optional(t.text({ lowercase: true })),\n\n /**\n * Built-in log formats.\n * - \"json\" - JSON format, useful for structured logging and log aggregation. {@link JsonFormatterProvider}\n * - \"pretty\" - Simple text format, human-readable, with colors. {@link PrettyFormatterProvider}\n * - \"raw\" - Raw format, no formatting, just the message. {@link RawFormatterProvider}\n */\n LOG_FORMAT: t.optional(\n t.enum([\"json\", \"pretty\", \"raw\"], { lowercase: true }),\n ),\n});\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n export interface Env extends Partial<Static<typeof envSchema>> {}\n\n export interface State {\n /**\n * Current log level for the application or specific modules.\n */\n \"alepha.logger.level\"?: string;\n }\n\n export interface Hooks {\n log: {\n message?: string;\n entry: LogEntry;\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["envSchema"],"sources":["../../src/logger/providers/LogDestinationProvider.ts","../../src/logger/providers/LogFormatterProvider.ts","../../src/logger/services/Logger.ts","../../src/logger/primitives/$logger.ts","../../src/logger/providers/ConsoleColorProvider.ts","../../src/logger/providers/ConsoleDestinationProvider.ts","../../src/logger/providers/JsonFormatterProvider.ts","../../src/logger/providers/MemoryDestinationProvider.ts","../../src/logger/providers/PrettyFormatterProvider.ts","../../src/logger/providers/RawFormatterProvider.ts","../../src/logger/schemas/logEntrySchema.ts","../../src/logger/index.ts"],"sourcesContent":["import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\n\nexport abstract class LogDestinationProvider {\n public abstract write(message: string, entry: LogEntry): void;\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\n\nexport abstract class LogFormatterProvider {\n public abstract format(entry: LogEntry): string;\n}\n","import {\n $inject,\n Alepha,\n AlephaError,\n type LoggerInterface,\n type LogLevel,\n} from \"alepha\";\nimport { DateTimeProvider } from \"alepha/datetime\";\nimport { LogDestinationProvider } from \"../providers/LogDestinationProvider.ts\";\nimport { LogFormatterProvider } from \"../providers/LogFormatterProvider.ts\";\nimport type { LogEntry } from \"../schemas/logEntrySchema.ts\";\n\nexport class Logger implements LoggerInterface {\n protected readonly alepha = $inject(Alepha);\n protected readonly formatter = $inject(LogFormatterProvider);\n protected readonly destination = $inject(LogDestinationProvider);\n protected readonly dateTimeProvider = $inject(DateTimeProvider);\n\n protected readonly levels: Record<string, number> = {\n SILENT: -1,\n ERROR: 0,\n WARN: 1,\n INFO: 2,\n DEBUG: 3,\n TRACE: 4,\n };\n\n protected readonly service: string;\n protected readonly module: string;\n protected readonly app?: string;\n\n protected appLogLevel: string = \"INFO\";\n protected logLevel: LogLevel = \"INFO\";\n\n constructor(service: string, module: string) {\n this.service = service;\n this.module = module;\n this.app = this.alepha.env.APP_NAME;\n }\n\n public get context(): string | undefined {\n return this.alepha.context.get<string>(\"context\");\n }\n\n public get level(): string {\n const stateLogLevel = this.alepha.store.get(\"alepha.logger.level\");\n if (stateLogLevel && stateLogLevel !== this.appLogLevel) {\n this.appLogLevel = stateLogLevel;\n this.logLevel = this.parseLevel(this.appLogLevel, this.module);\n }\n return this.logLevel;\n }\n\n public parseLevel(level: string, app: string): LogLevel {\n const parts = level.toLowerCase().split(/[,;]/);\n\n // First pass: check for module-specific configurations\n for (const part of parts) {\n const trimmedPart = part.trim();\n if (!trimmedPart) continue; // Skip empty parts\n\n if (trimmedPart.includes(\":\") || trimmedPart.includes(\"=\")) {\n const [modulePattern, levelValue] = trimmedPart.split(/[:=]/);\n const trimmedModule = modulePattern.trim();\n const trimmedLevel = levelValue?.trim();\n\n if (!trimmedLevel) continue; // Skip if no level specified\n\n if (this.matchesPattern(app, trimmedModule)) {\n try {\n return this.asLogLevel(trimmedLevel);\n } catch (error) {\n throw new AlephaError(\n `Invalid log level '${levelValue?.trim()}' for module pattern '${trimmedModule}'`,\n );\n }\n }\n }\n }\n\n // Second pass: look for global level\n for (const part of parts) {\n const trimmedPart = part.trim();\n if (!trimmedPart) continue; // Skip empty parts\n\n if (!trimmedPart.includes(\":\") && !trimmedPart.includes(\"=\")) {\n try {\n return this.asLogLevel(trimmedPart);\n } catch (error) {\n throw new Error(`Invalid global log level \"${trimmedPart}\"`);\n }\n }\n }\n\n return \"INFO\";\n }\n\n private matchesPattern(moduleName: string, pattern: string): boolean {\n if (pattern.includes(\"*\")) {\n // Convert wildcard pattern to regex\n const regexPattern = pattern.replace(/\\./g, \"\\\\.\").replace(/\\*/g, \".*\");\n return new RegExp(`^${regexPattern}`).test(moduleName);\n }\n\n // Exact prefix match (existing behavior)\n return moduleName.startsWith(pattern);\n }\n\n public asLogLevel(something: string): LogLevel {\n const level = something.trim().toUpperCase();\n if (this.levels[level] !== undefined) {\n return level as LogLevel;\n }\n\n throw new AlephaError(`Invalid log level: ${something}`);\n }\n\n // -------------------------------------------------------------------------------------------------------------------\n\n public error(message: string, data?: unknown): void {\n this.log(\"ERROR\", message, data);\n }\n\n public warn(message: string, data?: unknown): void {\n this.log(\"WARN\", message, data);\n }\n\n public info(message: string, data?: unknown): void {\n this.log(\"INFO\", message, data);\n }\n\n public debug(message: string, data?: unknown): void {\n this.log(\"DEBUG\", message, data);\n }\n\n public trace(message: string, data?: unknown): void {\n this.log(\"TRACE\", message, data);\n }\n\n protected log(level: LogLevel, message: string, data?: unknown): void {\n let _message = \"\";\n if (typeof message === \"string\") {\n _message = message;\n } else if (typeof data === \"string\") {\n _message = data;\n }\n\n let _data: object | Error | undefined;\n if (typeof data === \"object\" && !!data) {\n _data = data;\n } else if (typeof message === \"object\" && message) {\n _data = message;\n }\n\n const logEntry: LogEntry = {\n level,\n message: _message,\n data: _data,\n context: this.context,\n service: this.service,\n module: this.module,\n app: this.app,\n timestamp: this.dateTimeProvider.nowMillis(),\n };\n\n if (this.levels[level] > this.levels[this.level]) {\n this.emit(logEntry);\n return;\n }\n\n const formatted = this.formatter.format(logEntry);\n\n this.emit(logEntry, formatted);\n\n this.destination.write(formatted, logEntry);\n }\n\n protected emit(entry: LogEntry, message?: string) {\n this.alepha.events\n .emit(\n \"log\",\n {\n message,\n entry,\n },\n {\n catch: true,\n },\n )\n .catch(() => null);\n }\n}\n","import { $context, $inject, KIND } from \"alepha\";\nimport { Logger } from \"../services/Logger.ts\";\n\n/**\n * Create a logger.\n *\n * `name` is optional, by default it will use the name of the service.\n *\n * @example\n * ```ts\n * import { $logger } from \"alepha\";\n *\n * class MyService {\n * \tlog = $logger();\n *\n * constructor() {\n * this.log.info(\"Service initialized\");\n * // print something like '[23:45:53.326] INFO <app.MyService>: Service initialized'\n * }\n * }\n * ```\n */\nexport const $logger = (options: LoggerPrimitiveOptions = {}): Logger => {\n const { alepha, service, module } = $context();\n\n return $inject(Logger, {\n lifetime: \"transient\",\n args: [\n options.name ?? service?.name ?? \"Func\",\n module?.name ?? alepha.env.MODULE_NAME ?? \"app\",\n ],\n });\n};\n\nexport interface LoggerPrimitiveOptions {\n name?: string;\n}\n\n$logger[KIND] = Logger;\n","import { $env, $inject, Alepha, t } from \"alepha\";\n\nconst envSchema = t.object({\n /**\n * Disable colors in the console output.\n */\n NO_COLOR: t.optional(t.text()),\n\n /**\n * Force color output for the application.\n */\n FORCE_COLOR: t.optional(t.text()),\n});\n\nexport class ConsoleColorProvider {\n static readonly COLORS = {\n RESET: \"\\x1b[0m\",\n BLACK: \"\\x1b[30m\",\n RED: \"\\x1b[31m\",\n GREEN: \"\\x1b[32m\",\n ORANGE: \"\\x1b[33m\", // using yellow for orange-ish\n BLUE: \"\\x1b[34m\",\n PURPLE: \"\\x1b[35m\",\n CYAN: \"\\x1b[36m\",\n GREY_LIGHT: \"\\x1b[37m\",\n GREY_LIGHT_BOLD: \"\\x1b[1;37m\",\n GREY_DARK: \"\\x1b[90m\",\n GREY_DARK_BOLD: \"\\x1b[1;90m\",\n WHITE: \"\\x1b[97m\",\n WHITE_BOLD: \"\\x1b[1;97m\",\n // levels\n SILENT: \"\",\n ERROR: \"\\x1b[31m\",\n WARN: \"\\x1b[33m\",\n INFO: \"\\x1b[32m\",\n DEBUG: \"\\x1b[34m\",\n TRACE: \"\\x1b[90m\",\n };\n\n protected readonly env = $env(envSchema);\n protected readonly alepha = $inject(Alepha);\n\n protected enabled = true;\n\n constructor() {\n this.enabled = this.isEnabled();\n }\n\n public isEnabled(): boolean {\n if (this.env.NO_COLOR) {\n return false;\n }\n\n if (this.env.FORCE_COLOR) {\n return true;\n }\n\n return !this.alepha.isProduction();\n }\n\n public set(\n color: keyof typeof ConsoleColorProvider.COLORS,\n text: string,\n reset: string = ConsoleColorProvider.COLORS.RESET,\n ): string {\n if (!this.enabled) {\n return text;\n }\n\n return `${ConsoleColorProvider.COLORS[color]}${text}${reset}`;\n }\n}\n","import { LogDestinationProvider } from \"./LogDestinationProvider.ts\";\n\nexport class ConsoleDestinationProvider extends LogDestinationProvider {\n public write(message: string): void {\n console.log(message);\n }\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { LogFormatterProvider } from \"./LogFormatterProvider.ts\";\n\nexport class JsonFormatterProvider extends LogFormatterProvider {\n public format(entry: LogEntry): string {\n const json: Record<string, any> = {\n level: entry.level,\n message: entry.message,\n context: entry.context,\n service: entry.service,\n module: entry.module,\n app: entry.app,\n time: entry.timestamp,\n };\n\n if (entry.data instanceof Error) {\n json.error = this.formatJsonError(entry.data);\n } else {\n json.data = entry.data;\n }\n\n return JSON.stringify(json);\n }\n\n public formatJsonError(error: Error): object {\n return {\n name: error.name,\n message: error.message,\n stack: error.stack,\n cause:\n error.cause instanceof Error\n ? this.formatJsonError(error.cause)\n : undefined,\n };\n }\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { LogDestinationProvider } from \"./LogDestinationProvider.ts\";\n\nexport class MemoryDestinationProvider extends LogDestinationProvider {\n protected entries: Array<LogEntry & { formatted: string }> = [];\n\n public readonly options = {\n maxEntries: 1000,\n };\n\n public write(formatted: string, entry: LogEntry): void {\n this.entries.push({ ...entry, formatted });\n\n if (this.entries.length > this.options.maxEntries) {\n this.entries = this.entries.slice(\n -Math.floor(this.options.maxEntries * 0.8),\n );\n }\n }\n\n public get logs() {\n return [...this.entries];\n }\n\n public clear(): void {\n this.entries = [];\n }\n}\n","import { $inject, Alepha } from \"alepha\";\nimport type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { ConsoleColorProvider } from \"./ConsoleColorProvider.ts\";\nimport { LogFormatterProvider } from \"./LogFormatterProvider.ts\";\n\nexport class PrettyFormatterProvider extends LogFormatterProvider {\n protected color = $inject(ConsoleColorProvider);\n protected alepha = $inject(Alepha);\n\n public format(entry: LogEntry): string {\n const { data, timestamp } = entry;\n\n let output = \"\";\n let details = \"\";\n\n const isError = data instanceof Error;\n if (isError) {\n details = this.formatError(data);\n } else if (data) {\n try {\n details = JSON.stringify(data);\n } catch {\n details = \"[Unserializable Object]\";\n }\n }\n\n output += this.color.set(\n \"GREY_DARK\",\n `[${this.formatTimestamp(timestamp)}]`,\n );\n output += \" \";\n\n output += this.color.set(entry.level, entry.level.toUpperCase());\n output += \" \";\n\n if (entry.app) {\n output += this.color.set(\"GREY_DARK\", `${entry.app}`);\n output += \" \";\n }\n\n if (entry.context) {\n output += this.color.set(\n \"GREY_DARK\",\n `(${this.formatContext(entry.context)})`,\n );\n output += \" \";\n }\n\n const module = this.color.set(\"GREY_LIGHT\", `${entry.module}.`);\n const service = this.color.set(\n this.alepha.isBrowser() ? \"RESET\" : \"WHITE\",\n entry.service,\n );\n\n output += `<${module}${service}>`;\n\n if (entry.message) {\n output += `: ${this.color.set(\"CYAN\", entry.message)}`;\n } else {\n output += \":\";\n }\n\n if (details) {\n if (isError) {\n output += ` \\n${details}`;\n } else {\n output += ` ${this.color.set(\"GREY_DARK\", details)}`;\n }\n }\n\n return output;\n }\n\n public formatTimestamp(timestamp: number): string {\n const d = new Date(timestamp);\n const h = d.getHours();\n const m = d.getMinutes();\n const s = d.getSeconds();\n const ms = d.getMilliseconds();\n\n return `${this.pad2(h)}:${this.pad2(m)}:${this.pad2(s)}.${this.pad3(ms)}`;\n }\n\n protected pad2 = (n: number) => (n < 10 ? \"0\" : \"\") + n;\n protected pad3 = (n: number) =>\n n < 10 ? `00${n}` : n < 100 ? `0${n}` : `${n}`;\n\n /**\n * Avoid to display the whole UUID in development mode\n */\n protected formatContext(context: string): string {\n if (this.alepha.isProduction()) {\n return context;\n }\n\n return context.slice(0, 8);\n }\n\n protected formatError(error: Error): string {\n // Chrome does not like stack traces with ASCII colors\n // so we remove the stack trace from log and just print with console.error\n if (this.alepha.isBrowser()) {\n // call console.error in a separate tick to avoid messing with log order\n setTimeout(() => {\n console.error(error);\n });\n return \"\";\n }\n\n if (this.alepha.isViteDev()) {\n // Node.js - try to fix stack trace with Vite SSR helper\n // Actually, it works only because we have a global helper in viteAlephaDev.ts\n const gl = globalThis as Record<string, unknown>;\n if (typeof gl === \"object\" && typeof gl.ssrFixStacktrace === \"function\") {\n gl.ssrFixStacktrace(error);\n }\n }\n\n let str = error.stack ?? error.message;\n\n const anyError = error as any;\n while (anyError.cause && anyError.cause instanceof Error) {\n str += `\\nCaused by: ${anyError.cause.stack ?? anyError.cause.message}`;\n anyError.cause = anyError.cause.cause;\n }\n\n return str;\n }\n}\n","import type { LogEntry } from \"../schemas/logEntrySchema.ts\";\nimport { LogFormatterProvider } from \"./LogFormatterProvider.ts\";\n\nexport class RawFormatterProvider extends LogFormatterProvider {\n public format(entry: LogEntry): string {\n let output = \"\";\n\n output += `${entry.message}`;\n\n if (entry.data instanceof Error) {\n output += `\\n${entry.data.message}`;\n let cause = entry.data.cause;\n while (cause instanceof Error) {\n output += `\\nCaused by: ${cause.message}`;\n cause = cause.cause;\n }\n }\n\n return output;\n }\n}\n","import { type Static, t } from \"alepha\";\n\nexport const logEntrySchema = t.object({\n level: t.enum([\"SILENT\", \"TRACE\", \"DEBUG\", \"INFO\", \"WARN\", \"ERROR\"]),\n message: t.text({\n size: \"rich\",\n }),\n service: t.text(),\n module: t.text(),\n context: t.optional(t.text()),\n app: t.optional(t.text()),\n data: t.optional(t.any()),\n timestamp: t.number(),\n});\n\nexport type LogEntry = Static<typeof logEntrySchema>;\n","import { $module, type Static, t } from \"alepha\";\nimport { $logger } from \"./primitives/$logger.ts\";\nimport { ConsoleColorProvider } from \"./providers/ConsoleColorProvider.ts\";\nimport { ConsoleDestinationProvider } from \"./providers/ConsoleDestinationProvider.ts\";\nimport { JsonFormatterProvider } from \"./providers/JsonFormatterProvider.ts\";\nimport { LogDestinationProvider } from \"./providers/LogDestinationProvider.ts\";\nimport { LogFormatterProvider } from \"./providers/LogFormatterProvider.ts\";\nimport { MemoryDestinationProvider } from \"./providers/MemoryDestinationProvider.ts\";\nimport { PrettyFormatterProvider } from \"./providers/PrettyFormatterProvider.ts\";\nimport { RawFormatterProvider } from \"./providers/RawFormatterProvider.ts\";\nimport type { LogEntry } from \"./schemas/logEntrySchema.ts\";\nimport { Logger } from \"./services/Logger.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nexport * from \"./primitives/$logger.ts\";\nexport * from \"./providers/ConsoleColorProvider.ts\";\nexport * from \"./providers/ConsoleDestinationProvider.ts\";\nexport * from \"./providers/JsonFormatterProvider.ts\";\nexport * from \"./providers/LogDestinationProvider.ts\";\nexport * from \"./providers/LogFormatterProvider.ts\";\nexport * from \"./providers/MemoryDestinationProvider.ts\";\nexport * from \"./providers/PrettyFormatterProvider.ts\";\nexport * from \"./schemas/logEntrySchema.ts\";\nexport * from \"./services/Logger.ts\";\n\n// ---------------------------------------------------------------------------------------------------------------------\n\n/**\n * Minimalist logger module for Alepha.\n *\n * It offers a global logger interface (info, warn, ...) via the `$logger` primitive.\n *\n * ```ts\n * import { $logger } from \"alepha/logger\";\n *\n * class App {\n * log = $logger();\n * }\n * ```\n *\n * ### Formatting and Destinations\n *\n * `AlephaLogger` is **extensible**, destinations and formatters can be added or replaced.\n *\n * Default log destinations are:\n * - ConsoleDestinationProvider: logs to the console.\n * - MemoryDestinationProvider: stores logs in memory for later retrieval.\n *\n * Default log formatters are:\n * - JsonFormatterProvider: formats logs as JSON.\n * - SimpleFormatterProvider: formats logs as simple text (with colors when possible).\n * - RawFormatterProvider: formats logs as raw text without any formatting.\n *\n * ### Event Emission\n *\n * The logger emits 'log' events that can be listened to by external code, allowing for custom log processing and destinations.\n *\n * ```ts\n * class CustomDestination {\n * onLog = $hook({\n * on: \"log\",\n * handler: (ev) => {\n * // ev.message (formatted message)\n * // ev.entry (level, raw message, ...)\n * }\n * });\n * }\n * ```\n *\n * ### Log Level\n *\n * You can configure the log level and format via environment variables:\n *\n * - `LOG_LEVEL`: Sets the default log level for the application.\n * - `LOG_FORMAT`: Sets the default log format for the application.\n *\n * ```bash\n * LOG_LEVEL=debug LOG_FORMAT=json node src/index.ts\n * ```\n *\n * Log level is also available in the state as `logLevel`, which can be used to dynamically change the log level at runtime.\n * ```ts\n * alepha.state.set(\"alepha.logger.level\", \"debug\");\n * ```\n *\n * Log level is $module aware, meaning you can set different log levels for different modules.\n *\n * **Module-specific configuration:**\n * - `LOG_LEVEL=my.module.name:debug,info` - debug for `my.module.name` (and submodules), info for others\n * - `LOG_LEVEL=alepha:trace,my.app:error,info` - trace for alepha modules, error for my.app modules, info for others\n *\n * **Wildcard patterns (NEW):**\n * - `LOG_LEVEL=alepha.*:debug,info` - debug for all alepha submodules\n * - `LOG_LEVEL=*.test:silent,*.core:trace,info` - silent for test modules, trace for core modules\n */\nexport const AlephaLogger = $module({\n name: \"alepha.logger\",\n primitives: [$logger],\n services: [\n Logger,\n ConsoleDestinationProvider,\n MemoryDestinationProvider,\n JsonFormatterProvider,\n PrettyFormatterProvider,\n RawFormatterProvider,\n ConsoleColorProvider,\n ],\n register: (alepha) => {\n const env = alepha.parseEnv(envSchema);\n\n const getLogDestinationProvider = () => {\n // in test mode, if no LOG_LEVEL is set, use MemoryDestinationProvider to capture logs for inspection.\n // logs will be printed to console only if the test fails.\n if (alepha.isTest() && !env.LOG_LEVEL) {\n const printOnError = (ev: any) => {\n if (ev.task?.result?.state === \"fail\") {\n const output = alepha.inject(MemoryDestinationProvider);\n for (const log of output.logs) {\n console.log(log.formatted);\n }\n }\n };\n\n try {\n alepha.store.get(\"alepha.test.afterEach\")?.(printOnError);\n alepha.store.get(\"alepha.test.onTestFinished\")?.(printOnError);\n } catch {\n // ignore\n }\n\n return MemoryDestinationProvider;\n }\n\n return ConsoleDestinationProvider;\n };\n\n const getLogFormatterProvider = () => {\n if (env.LOG_FORMAT) {\n if (env.LOG_FORMAT === \"json\") {\n return JsonFormatterProvider;\n }\n if (env.LOG_FORMAT === \"raw\") {\n return RawFormatterProvider;\n }\n return PrettyFormatterProvider;\n }\n\n if (alepha.isProduction() && !alepha.isBrowser()) {\n return JsonFormatterProvider;\n }\n\n return PrettyFormatterProvider;\n };\n\n alepha.with({\n optional: true,\n provide: LogDestinationProvider,\n use: getLogDestinationProvider(),\n });\n\n alepha.with({\n optional: true,\n provide: LogFormatterProvider,\n use: getLogFormatterProvider(),\n });\n\n alepha.store.set(\n \"alepha.logger\",\n alepha.inject(Logger, {\n lifetime: \"transient\",\n args: [\"Alepha\", \"alepha.core\"],\n }),\n );\n\n alepha.store.set(\n \"alepha.logger.level\",\n env.LOG_LEVEL ?? (alepha.isTest() ? \"trace\" : \"info\"),\n );\n },\n});\n\n// ---------------------------------------------------------------------------------------------------------------------\n\nconst envSchema = t.object({\n /**\n * Default log level for the application.\n *\n * Default by environment:\n * - dev = info\n * - prod = info\n * - test = error\n *\n * Levels are: \"trace\" | \"debug\" | \"info\" | \"warn\" | \"error\" | \"silent\"\n *\n * Level can be set for a specific module:\n *\n * @example\n * LOG_LEVEL=my.module.name:debug,info # Set debug level for my.module.name and info for all other modules\n * LOG_LEVEL=alepha:trace, info # Set trace level for all alepha modules and info for all other modules\n */\n LOG_LEVEL: t.optional(\n t.text({\n description: `Application log level on startup.\nLevels are: trace, debug, info, warn, error, silent\nLevel can be set for a specific module:\n\"my.module.name:debug,info\" -> Set debug level for my.module.name and info for all other modules\n\"alepha:trace,info\" -> Set trace level for all alepha modules and info for all other modules`,\n lowercase: true,\n }),\n ),\n\n /**\n * Built-in log formats.\n * - \"json\" - JSON format, useful for structured logging and log aggregation. {@link JsonFormatterProvider}\n * - \"pretty\" - Simple text format, human-readable, with colors. {@link PrettyFormatterProvider}\n * - \"raw\" - Raw format, no formatting, just the message. {@link RawFormatterProvider}\n */\n LOG_FORMAT: t.optional(\n t.enum([\"json\", \"pretty\", \"raw\"], {\n description: \"Default log format for the application.\",\n lowercase: true,\n }),\n ),\n});\n\n// ---------------------------------------------------------------------------------------------------------------------\n\ndeclare module \"alepha\" {\n export interface Env extends Partial<Static<typeof envSchema>> {}\n\n export interface State {\n /**\n * Current log level for the application or specific modules.\n */\n \"alepha.logger.level\"?: string;\n }\n\n export interface Hooks {\n log: {\n message?: string;\n entry: LogEntry;\n };\n }\n}\n"],"mappings":"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"}
|