@warlock.js/core 5.29.0 → 5.30.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +58 -0
- package/esm/application/app.d.mts +1 -1
- package/esm/application/app.d.mts.map +1 -1
- package/esm/application/app.mjs +1 -1
- package/esm/application/app.mjs.map +1 -1
- package/esm/application/application-config-types.d.mts +1 -1
- package/esm/application/application-config-types.d.mts.map +1 -1
- package/esm/application/application.d.mts +1 -1
- package/esm/application/application.d.mts.map +1 -1
- package/esm/application/application.mjs +1 -1
- package/esm/application/application.mjs.map +1 -1
- package/esm/application/boot-signal.d.mts +1 -1
- package/esm/application/boot-signal.d.mts.map +1 -1
- package/esm/application/boot-signal.mjs +1 -1
- package/esm/application/boot-signal.mjs.map +1 -1
- package/esm/application/public-url.d.mts +1 -1
- package/esm/application/public-url.d.mts.map +1 -1
- package/esm/application/public-url.mjs +1 -1
- package/esm/application/public-url.mjs.map +1 -1
- package/esm/application/roles.d.mts +1 -1
- package/esm/application/roles.d.mts.map +1 -1
- package/esm/application/roles.mjs +1 -1
- package/esm/application/roles.mjs.map +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts +1 -1
- package/esm/benchmark/benchmark-snapshots.d.mts.map +1 -1
- package/esm/benchmark/benchmark-snapshots.mjs +1 -1
- package/esm/benchmark/benchmark-snapshots.mjs.map +1 -1
- package/esm/benchmark/benchmark.d.mts +1 -1
- package/esm/benchmark/benchmark.d.mts.map +1 -1
- package/esm/benchmark/benchmark.mjs +1 -1
- package/esm/benchmark/benchmark.mjs.map +1 -1
- package/esm/benchmark/channels/console.channel.d.mts +1 -1
- package/esm/benchmark/channels/console.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/console.channel.mjs +1 -1
- package/esm/benchmark/channels/console.channel.mjs.map +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts +1 -1
- package/esm/benchmark/channels/noop.channel.d.mts.map +1 -1
- package/esm/benchmark/channels/noop.channel.mjs +1 -1
- package/esm/benchmark/channels/noop.channel.mjs.map +1 -1
- package/esm/benchmark/profiler.d.mts +1 -1
- package/esm/benchmark/profiler.d.mts.map +1 -1
- package/esm/benchmark/profiler.mjs +1 -1
- package/esm/benchmark/profiler.mjs.map +1 -1
- package/esm/benchmark/types.d.mts +1 -1
- package/esm/benchmark/types.d.mts.map +1 -1
- package/esm/bootstrap/setup.d.mts +1 -1
- package/esm/bootstrap/setup.d.mts.map +1 -1
- package/esm/bootstrap/setup.mjs +1 -1
- package/esm/bootstrap/setup.mjs.map +1 -1
- package/esm/bootstrap.d.mts +1 -1
- package/esm/bootstrap.d.mts.map +1 -1
- package/esm/bootstrap.mjs +1 -1
- package/esm/bootstrap.mjs.map +1 -1
- package/esm/cache/database-cache-driver.d.mts +1 -1
- package/esm/cache/database-cache-driver.d.mts.map +1 -1
- package/esm/cache/database-cache-driver.mjs +1 -1
- package/esm/cache/database-cache-driver.mjs.map +1 -1
- package/esm/cache/index.mjs +1 -1
- package/esm/cache/index.mjs.map +1 -1
- package/esm/cli/cli-commands.manager.mjs +1 -1
- package/esm/cli/cli-commands.manager.mjs.map +1 -1
- package/esm/cli/cli-commands.utils.mjs +1 -1
- package/esm/cli/cli-commands.utils.mjs.map +1 -1
- package/esm/cli/commands/add.command.mjs +1 -1
- package/esm/cli/commands/add.command.mjs.map +1 -1
- package/esm/cli/commands/build.command.mjs +1 -1
- package/esm/cli/commands/build.command.mjs.map +1 -1
- package/esm/cli/commands/create-database.command.mjs +1 -1
- package/esm/cli/commands/create-database.command.mjs.map +1 -1
- package/esm/cli/commands/dev-server.command.mjs +1 -1
- package/esm/cli/commands/dev-server.command.mjs.map +1 -1
- package/esm/cli/commands/doctor/boot-for-diagnostics.mjs +1 -1
- package/esm/cli/commands/doctor/boot-for-diagnostics.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/config.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/config.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/connectors.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/connectors.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/handler-signature.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/handler-signature.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/health.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/health.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/index.mjs +1 -1
- package/esm/cli/commands/doctor/checks/index.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/jwt-secret.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/locales-ts-deprecated.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/optional-peers.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/release-hygiene.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/checks/routes.check.mjs +1 -1
- package/esm/cli/commands/doctor/checks/routes.check.mjs.map +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs +1 -1
- package/esm/cli/commands/doctor/doctor-command.action.mjs.map +1 -1
- package/esm/cli/commands/doctor/format-report.mjs +1 -1
- package/esm/cli/commands/doctor/format-report.mjs.map +1 -1
- package/esm/cli/commands/doctor/run-checks.mjs +1 -1
- package/esm/cli/commands/doctor/run-checks.mjs.map +1 -1
- package/esm/cli/commands/doctor.command.mjs +1 -1
- package/esm/cli/commands/doctor.command.mjs.map +1 -1
- package/esm/cli/commands/drop-tables.command.mjs +1 -1
- package/esm/cli/commands/drop-tables.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generate.command.mjs +1 -1
- package/esm/cli/commands/generate/generate.command.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs +1 -1
- package/esm/cli/commands/generate/generators/column-dsl-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/controller.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/migration.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/model.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/module.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/repository.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/resource.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/service.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/generators/use-case.generator.mjs +1 -1
- package/esm/cli/commands/generate/generators/use-case.generator.mjs.map +1 -1
- package/esm/cli/commands/generate/templates/stubs.mjs +1 -1
- package/esm/cli/commands/generate/templates/stubs.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs +1 -1
- package/esm/cli/commands/generate/utils/name-parser.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs +1 -1
- package/esm/cli/commands/generate/utils/path-resolver.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/prompt.mjs +1 -1
- package/esm/cli/commands/generate/utils/prompt.mjs.map +1 -1
- package/esm/cli/commands/generate/utils/writer.mjs +1 -1
- package/esm/cli/commands/generate/utils/writer.mjs.map +1 -1
- package/esm/cli/commands/migrate.command.mjs +1 -1
- package/esm/cli/commands/migrate.command.mjs.map +1 -1
- package/esm/cli/commands/openapi-generator.action.mjs +1 -1
- package/esm/cli/commands/openapi-generator.action.mjs.map +1 -1
- package/esm/cli/commands/openapi-generator.command.mjs +1 -1
- package/esm/cli/commands/openapi-generator.command.mjs.map +1 -1
- package/esm/cli/commands/postman-generator.action.mjs +1 -1
- package/esm/cli/commands/postman-generator.action.mjs.map +1 -1
- package/esm/cli/commands/postman-generator.command.mjs +1 -1
- package/esm/cli/commands/postman-generator.command.mjs.map +1 -1
- package/esm/cli/commands/routes/diff-page-routes.mjs +1 -1
- package/esm/cli/commands/routes/diff-page-routes.mjs.map +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs +1 -1
- package/esm/cli/commands/routes/format-routes-table.mjs.map +1 -1
- package/esm/cli/commands/routes/route-row.mjs +1 -1
- package/esm/cli/commands/routes/route-row.mjs.map +1 -1
- package/esm/cli/commands/routes/routes-command.action.mjs +1 -1
- package/esm/cli/commands/routes/routes-command.action.mjs.map +1 -1
- package/esm/cli/commands/routes/routes-diff.action.mjs +1 -1
- package/esm/cli/commands/routes/routes-diff.action.mjs.map +1 -1
- package/esm/cli/commands/routes/with-console-on-stderr.mjs +1 -1
- package/esm/cli/commands/routes/with-console-on-stderr.mjs.map +1 -1
- package/esm/cli/commands/routes.command.mjs +1 -1
- package/esm/cli/commands/routes.command.mjs.map +1 -1
- package/esm/cli/commands/seed.command.mjs +1 -1
- package/esm/cli/commands/seed.command.mjs.map +1 -1
- package/esm/cli/commands/start-production.command.mjs +1 -1
- package/esm/cli/commands/start-production.command.mjs.map +1 -1
- package/esm/cli/commands/storage-put.action.mjs +1 -1
- package/esm/cli/commands/storage-put.action.mjs.map +1 -1
- package/esm/cli/commands/storage-put.command.mjs +1 -1
- package/esm/cli/commands/storage-put.command.mjs.map +1 -1
- package/esm/cli/commands/typings-generator.command.mjs +1 -1
- package/esm/cli/commands/typings-generator.command.mjs.map +1 -1
- package/esm/cli/commands/update.command.mjs +1 -1
- package/esm/cli/commands/update.command.mjs.map +1 -1
- package/esm/cli/commands-loader.mjs +1 -1
- package/esm/cli/commands-loader.mjs.map +1 -1
- package/esm/cli/framework-cli-commands.mjs +1 -1
- package/esm/cli/framework-cli-commands.mjs.map +1 -1
- package/esm/cli/parse-cli-args.mjs +1 -1
- package/esm/cli/parse-cli-args.mjs.map +1 -1
- package/esm/cli/start.mjs +1 -1
- package/esm/cli/start.mjs.map +1 -1
- package/esm/cli/string-similarity.mjs +1 -1
- package/esm/cli/string-similarity.mjs.map +1 -1
- package/esm/commands/cli-command.d.mts +1 -1
- package/esm/commands/cli-command.d.mts.map +1 -1
- package/esm/commands/cli-command.mjs +1 -1
- package/esm/commands/cli-command.mjs.map +1 -1
- package/esm/commands/types.d.mts +1 -1
- package/esm/commands/types.d.mts.map +1 -1
- package/esm/config/config-getter.d.mts +1 -1
- package/esm/config/config-getter.d.mts.map +1 -1
- package/esm/config/config-getter.mjs +1 -1
- package/esm/config/config-getter.mjs.map +1 -1
- package/esm/config/config-handlers.d.mts +1 -1
- package/esm/config/config-handlers.d.mts.map +1 -1
- package/esm/config/config-handlers.mjs +1 -1
- package/esm/config/config-handlers.mjs.map +1 -1
- package/esm/config/config-key-from-path.mjs +1 -1
- package/esm/config/config-key-from-path.mjs.map +1 -1
- package/esm/config/config-loader.d.mts +1 -1
- package/esm/config/config-loader.d.mts.map +1 -1
- package/esm/config/config-loader.mjs +1 -1
- package/esm/config/config-loader.mjs.map +1 -1
- package/esm/config/config-manager.mjs +1 -1
- package/esm/config/config-manager.mjs.map +1 -1
- package/esm/config/config-setter.d.mts +1 -1
- package/esm/config/config-setter.d.mts.map +1 -1
- package/esm/config/config-setter.mjs +1 -1
- package/esm/config/config-setter.mjs.map +1 -1
- package/esm/config/config-special-handlers.d.mts +1 -1
- package/esm/config/config-special-handlers.d.mts.map +1 -1
- package/esm/config/config-special-handlers.mjs +1 -1
- package/esm/config/config-special-handlers.mjs.map +1 -1
- package/esm/config/load-config-files.mjs +1 -1
- package/esm/config/load-config-files.mjs.map +1 -1
- package/esm/config/locale-configuration.mjs +1 -1
- package/esm/config/locale-configuration.mjs.map +1 -1
- package/esm/config/types.d.mts +1 -1
- package/esm/config/types.d.mts.map +1 -1
- package/esm/connectors/access-connector.d.mts +1 -1
- package/esm/connectors/access-connector.d.mts.map +1 -1
- package/esm/connectors/access-connector.mjs +1 -1
- package/esm/connectors/access-connector.mjs.map +1 -1
- package/esm/connectors/ai-connector.d.mts +1 -1
- package/esm/connectors/ai-connector.d.mts.map +1 -1
- package/esm/connectors/ai-connector.mjs +1 -1
- package/esm/connectors/ai-connector.mjs.map +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.d.mts +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.mjs +1 -1
- package/esm/connectors/assert-no-reserved-connector-names.mjs.map +1 -1
- package/esm/connectors/assert-unique-connector-names.d.mts +1 -1
- package/esm/connectors/assert-unique-connector-names.d.mts.map +1 -1
- package/esm/connectors/assert-unique-connector-names.mjs +1 -1
- package/esm/connectors/assert-unique-connector-names.mjs.map +1 -1
- package/esm/connectors/base-connector.d.mts +1 -1
- package/esm/connectors/base-connector.d.mts.map +1 -1
- package/esm/connectors/base-connector.mjs +1 -1
- package/esm/connectors/base-connector.mjs.map +1 -1
- package/esm/connectors/cache-connector.d.mts +1 -1
- package/esm/connectors/cache-connector.d.mts.map +1 -1
- package/esm/connectors/cache-connector.mjs +1 -1
- package/esm/connectors/cache-connector.mjs.map +1 -1
- package/esm/connectors/connectors-manager.d.mts +1 -1
- package/esm/connectors/connectors-manager.d.mts.map +1 -1
- package/esm/connectors/connectors-manager.mjs +2 -2
- package/esm/connectors/connectors-manager.mjs.map +1 -1
- package/esm/connectors/database-connector.d.mts +1 -1
- package/esm/connectors/database-connector.d.mts.map +1 -1
- package/esm/connectors/database-connector.mjs +1 -1
- package/esm/connectors/database-connector.mjs.map +1 -1
- package/esm/connectors/describe-server-address.mjs +1 -1
- package/esm/connectors/describe-server-address.mjs.map +1 -1
- package/esm/connectors/herald-connector.d.mts +1 -1
- package/esm/connectors/herald-connector.d.mts.map +1 -1
- package/esm/connectors/herald-connector.mjs +1 -1
- package/esm/connectors/herald-connector.mjs.map +1 -1
- package/esm/connectors/http-connector.d.mts +1 -1
- package/esm/connectors/http-connector.d.mts.map +1 -1
- package/esm/connectors/http-connector.mjs +1 -1
- package/esm/connectors/http-connector.mjs.map +1 -1
- package/esm/connectors/logger-connector.d.mts +1 -1
- package/esm/connectors/logger-connector.d.mts.map +1 -1
- package/esm/connectors/logger-connector.mjs +1 -1
- package/esm/connectors/logger-connector.mjs.map +1 -1
- package/esm/connectors/mail-connector.d.mts +1 -1
- package/esm/connectors/mail-connector.d.mts.map +1 -1
- package/esm/connectors/mail-connector.mjs +1 -1
- package/esm/connectors/mail-connector.mjs.map +1 -1
- package/esm/connectors/notifications-connector.d.mts +1 -1
- package/esm/connectors/notifications-connector.d.mts.map +1 -1
- package/esm/connectors/notifications-connector.mjs +1 -1
- package/esm/connectors/notifications-connector.mjs.map +1 -1
- package/esm/connectors/read-bound-port.mjs +1 -1
- package/esm/connectors/read-bound-port.mjs.map +1 -1
- package/esm/connectors/register-configured-connectors.d.mts +1 -1
- package/esm/connectors/register-configured-connectors.d.mts.map +1 -1
- package/esm/connectors/register-configured-connectors.mjs +1 -1
- package/esm/connectors/register-configured-connectors.mjs.map +1 -1
- package/esm/connectors/single-server-warnings.mjs +1 -1
- package/esm/connectors/single-server-warnings.mjs.map +1 -1
- package/esm/connectors/socket-connector.d.mts +1 -1
- package/esm/connectors/socket-connector.d.mts.map +1 -1
- package/esm/connectors/socket-connector.mjs +1 -1
- package/esm/connectors/socket-connector.mjs.map +1 -1
- package/esm/connectors/storage.connector.d.mts +1 -1
- package/esm/connectors/storage.connector.d.mts.map +1 -1
- package/esm/connectors/storage.connector.mjs +1 -1
- package/esm/connectors/storage.connector.mjs.map +1 -1
- package/esm/connectors/types.d.mts +1 -1
- package/esm/connectors/types.d.mts.map +1 -1
- package/esm/connectors/types.mjs +1 -1
- package/esm/connectors/types.mjs.map +1 -1
- package/esm/container/container-instance-registry.mjs +1 -1
- package/esm/container/container-instance-registry.mjs.map +1 -1
- package/esm/container/development-app-modules.d.mts +1 -1
- package/esm/container/development-app-modules.d.mts.map +1 -1
- package/esm/container/development-model-modules.d.mts +1 -1
- package/esm/container/development-model-modules.d.mts.map +1 -1
- package/esm/container/index.d.mts +1 -1
- package/esm/container/index.d.mts.map +1 -1
- package/esm/container/index.mjs +1 -1
- package/esm/container/index.mjs.map +1 -1
- package/esm/database/create-database-action.mjs +1 -1
- package/esm/database/create-database-action.mjs.map +1 -1
- package/esm/database/drop-tables-action.mjs +1 -1
- package/esm/database/drop-tables-action.mjs.map +1 -1
- package/esm/database/migrate-action.mjs +1 -1
- package/esm/database/migrate-action.mjs.map +1 -1
- package/esm/database/models/database-log/database-log.d.mts +31 -39
- package/esm/database/models/database-log/database-log.d.mts.map +1 -1
- package/esm/database/models/database-log/database-log.mjs +1 -1
- package/esm/database/models/database-log/database-log.mjs.map +1 -1
- package/esm/database/pending-exit-code.mjs +1 -1
- package/esm/database/pending-exit-code.mjs.map +1 -1
- package/esm/database/resolve-pending-migrations.mjs +1 -1
- package/esm/database/resolve-pending-migrations.mjs.map +1 -1
- package/esm/database/seed-command-action.mjs +1 -1
- package/esm/database/seed-command-action.mjs.map +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs +1 -1
- package/esm/database/seeds/seed-records-table-migration.mjs.map +1 -1
- package/esm/database/seeds/seeder.d.mts +1 -1
- package/esm/database/seeds/seeder.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.d.mts +1 -1
- package/esm/database/seeds/seeder.errors.d.mts.map +1 -1
- package/esm/database/seeds/seeder.errors.mjs +1 -1
- package/esm/database/seeds/seeder.errors.mjs.map +1 -1
- package/esm/database/seeds/seeder.mjs +1 -1
- package/esm/database/seeds/seeder.mjs.map +1 -1
- package/esm/database/seeds/seeders.manager.mjs +1 -1
- package/esm/database/seeds/seeders.manager.mjs.map +1 -1
- package/esm/database/seeds/seeds-table-migration.mjs +1 -1
- package/esm/database/seeds/seeds-table-migration.mjs.map +1 -1
- package/esm/database/seeds/types.d.mts +1 -1
- package/esm/database/seeds/types.d.mts.map +1 -1
- package/esm/database/seeds/utils.mjs +1 -1
- package/esm/database/seeds/utils.mjs.map +1 -1
- package/esm/database/utils.d.mts +1 -1
- package/esm/database/utils.d.mts.map +1 -1
- package/esm/database/utils.mjs +1 -1
- package/esm/database/utils.mjs.map +1 -1
- package/esm/dev-server/app-module-registry.mjs +1 -1
- package/esm/dev-server/app-module-registry.mjs.map +1 -1
- package/esm/dev-server/boot-precondition-error.mjs +1 -1
- package/esm/dev-server/boot-precondition-error.mjs.map +1 -1
- package/esm/dev-server/build-development-openapi-document.mjs +1 -1
- package/esm/dev-server/build-development-openapi-document.mjs.map +1 -1
- package/esm/dev-server/check-for-updates.mjs +1 -1
- package/esm/dev-server/check-for-updates.mjs.map +1 -1
- package/esm/dev-server/collect-development-api-routes.mjs +1 -1
- package/esm/dev-server/collect-development-api-routes.mjs.map +1 -1
- package/esm/dev-server/create-worker.mjs +1 -1
- package/esm/dev-server/create-worker.mjs.map +1 -1
- package/esm/dev-server/dependency-graph.d.mts +1 -1
- package/esm/dev-server/dependency-graph.d.mts.map +1 -1
- package/esm/dev-server/dependency-graph.mjs +1 -1
- package/esm/dev-server/dependency-graph.mjs.map +1 -1
- package/esm/dev-server/dev-logger.mjs +1 -1
- package/esm/dev-server/dev-logger.mjs.map +1 -1
- package/esm/dev-server/development-server.mjs +1 -1
- package/esm/dev-server/development-server.mjs.map +1 -1
- package/esm/dev-server/events.mjs +1 -1
- package/esm/dev-server/events.mjs.map +1 -1
- package/esm/dev-server/extract-translation-keys.mjs +1 -1
- package/esm/dev-server/extract-translation-keys.mjs.map +1 -1
- package/esm/dev-server/file-event-handler.mjs +1 -1
- package/esm/dev-server/file-event-handler.mjs.map +1 -1
- package/esm/dev-server/file-manager.d.mts +1 -1
- package/esm/dev-server/file-manager.d.mts.map +1 -1
- package/esm/dev-server/file-manager.mjs +1 -1
- package/esm/dev-server/file-manager.mjs.map +1 -1
- package/esm/dev-server/file-operations.d.mts +1 -1
- package/esm/dev-server/file-operations.d.mts.map +1 -1
- package/esm/dev-server/file-operations.mjs +1 -1
- package/esm/dev-server/file-operations.mjs.map +1 -1
- package/esm/dev-server/files-orchestrator.mjs +20 -17
- package/esm/dev-server/files-orchestrator.mjs.map +1 -1
- package/esm/dev-server/files-watcher.mjs +1 -1
- package/esm/dev-server/files-watcher.mjs.map +1 -1
- package/esm/dev-server/flags.mjs +1 -1
- package/esm/dev-server/flags.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/base-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/eslint-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs +1 -1
- package/esm/dev-server/health-checker/checkers/typescript-health-checker.mjs.map +1 -1
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts +1 -1
- package/esm/dev-server/health-checker/file-health-checker.contract.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts +1 -1
- package/esm/dev-server/health-checker/file-health-result.d.mts.map +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs +1 -1
- package/esm/dev-server/health-checker/file-health-result.mjs.map +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs +1 -1
- package/esm/dev-server/health-checker/files-healthcare.manager.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs +1 -1
- package/esm/dev-server/health-checker/workers/eslint-health.worker.mjs.map +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs +1 -1
- package/esm/dev-server/health-checker/workers/ts-health.worker.mjs.map +1 -1
- package/esm/dev-server/layer-executor.mjs +1 -1
- package/esm/dev-server/layer-executor.mjs.map +1 -1
- package/esm/dev-server/legacy-locales-warning.mjs +1 -1
- package/esm/dev-server/legacy-locales-warning.mjs.map +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs +1 -1
- package/esm/dev-server/loader/build-transpile-init.mjs.map +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts +1 -1
- package/esm/dev-server/loader/hook-thread.d.mts.map +1 -1
- package/esm/dev-server/loader/hook-thread.mjs +1 -1
- package/esm/dev-server/loader/hook-thread.mjs.map +1 -1
- package/esm/dev-server/loader/load-hook.d.mts +1 -1
- package/esm/dev-server/loader/load-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/load-hook.mjs +1 -1
- package/esm/dev-server/loader/load-hook.mjs.map +1 -1
- package/esm/dev-server/loader/loader-port-acks.mjs +34 -0
- package/esm/dev-server/loader/loader-port-acks.mjs.map +1 -0
- package/esm/dev-server/loader/own-resolver.mjs +1 -1
- package/esm/dev-server/loader/own-resolver.mjs.map +1 -1
- package/esm/dev-server/loader/register-loader.mjs +1 -1
- package/esm/dev-server/loader/register-loader.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-capture.mjs +1 -1
- package/esm/dev-server/loader/resolve-capture.mjs.map +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts +1 -1
- package/esm/dev-server/loader/resolve-hook.d.mts.map +1 -1
- package/esm/dev-server/loader/resolve-hook.mjs +2 -2
- package/esm/dev-server/loader/resolve-hook.mjs.map +1 -1
- package/esm/dev-server/loader/source-slug.mjs +1 -1
- package/esm/dev-server/loader/source-slug.mjs.map +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs +1 -1
- package/esm/dev-server/loader/transpile-cache.mjs.map +1 -1
- package/esm/dev-server/loader/version-registry.mjs +1 -1
- package/esm/dev-server/loader/version-registry.mjs.map +1 -1
- package/esm/dev-server/manifest-manager.d.mts +1 -1
- package/esm/dev-server/manifest-manager.d.mts.map +1 -1
- package/esm/dev-server/manifest-manager.mjs +1 -1
- package/esm/dev-server/manifest-manager.mjs.map +1 -1
- package/esm/dev-server/model-module-registry.mjs +1 -1
- package/esm/dev-server/model-module-registry.mjs.map +1 -1
- package/esm/dev-server/model-resource-typings.mjs +1 -1
- package/esm/dev-server/model-resource-typings.mjs.map +1 -1
- package/esm/dev-server/module-loader.mjs +1 -1
- package/esm/dev-server/module-loader.mjs.map +1 -1
- package/esm/dev-server/package-json-manager.mjs +1 -1
- package/esm/dev-server/package-json-manager.mjs.map +1 -1
- package/esm/dev-server/parse-imports.mjs +73 -6
- package/esm/dev-server/parse-imports.mjs.map +1 -1
- package/esm/dev-server/read-config-ast.mjs +1 -1
- package/esm/dev-server/read-config-ast.mjs.map +1 -1
- package/esm/dev-server/ready-block.mjs +1 -1
- package/esm/dev-server/ready-block.mjs.map +1 -1
- package/esm/dev-server/register-dev-shortcuts.mjs +1 -1
- package/esm/dev-server/register-dev-shortcuts.mjs.map +1 -1
- package/esm/dev-server/register-installed-devtools.mjs +1 -1
- package/esm/dev-server/register-installed-devtools.mjs.map +1 -1
- package/esm/dev-server/restart-dev-server.mjs +1 -1
- package/esm/dev-server/restart-dev-server.mjs.map +1 -1
- package/esm/dev-server/route-types-publisher.mjs +1 -1
- package/esm/dev-server/route-types-publisher.mjs.map +1 -1
- package/esm/dev-server/run-connector-typings.mjs +1 -1
- package/esm/dev-server/run-connector-typings.mjs.map +1 -1
- package/esm/dev-server/run-typings-generation.mjs +1 -1
- package/esm/dev-server/run-typings-generation.mjs.map +1 -1
- package/esm/dev-server/shortcuts.mjs +1 -1
- package/esm/dev-server/shortcuts.mjs.map +1 -1
- package/esm/dev-server/special-file-patterns.mjs +1 -1
- package/esm/dev-server/special-file-patterns.mjs.map +1 -1
- package/esm/dev-server/special-files-collector.d.mts +1 -1
- package/esm/dev-server/special-files-collector.d.mts.map +1 -1
- package/esm/dev-server/special-files-collector.mjs +1 -1
- package/esm/dev-server/special-files-collector.mjs.map +1 -1
- package/esm/dev-server/start-development-server.mjs +1 -1
- package/esm/dev-server/start-development-server.mjs.map +1 -1
- package/esm/dev-server/supervisor.mjs +1 -1
- package/esm/dev-server/supervisor.mjs.map +1 -1
- package/esm/dev-server/translation-keys-sources.mjs +1 -1
- package/esm/dev-server/translation-keys-sources.mjs.map +1 -1
- package/esm/dev-server/tsconfig-manager.mjs +1 -1
- package/esm/dev-server/tsconfig-manager.mjs.map +1 -1
- package/esm/dev-server/type-generator.mjs +32 -11
- package/esm/dev-server/type-generator.mjs.map +1 -1
- package/esm/dev-server/types.d.mts +1 -1
- package/esm/dev-server/types.d.mts.map +1 -1
- package/esm/dev-server/update-check-cache.mjs +1 -1
- package/esm/dev-server/update-check-cache.mjs.map +1 -1
- package/esm/dev-server/utils.mjs +1 -1
- package/esm/dev-server/utils.mjs.map +1 -1
- package/esm/encryption/encrypt.d.mts +1 -1
- package/esm/encryption/encrypt.d.mts.map +1 -1
- package/esm/encryption/encrypt.mjs +1 -1
- package/esm/encryption/encrypt.mjs.map +1 -1
- package/esm/encryption/hash.d.mts +1 -1
- package/esm/encryption/hash.d.mts.map +1 -1
- package/esm/encryption/hash.mjs +1 -1
- package/esm/encryption/hash.mjs.map +1 -1
- package/esm/encryption/password.d.mts +1 -1
- package/esm/encryption/password.d.mts.map +1 -1
- package/esm/encryption/password.mjs +1 -1
- package/esm/encryption/password.mjs.map +1 -1
- package/esm/encryption/types.d.mts +1 -1
- package/esm/encryption/types.d.mts.map +1 -1
- package/esm/errors/container-key-missing-error.mjs +1 -1
- package/esm/errors/container-key-missing-error.mjs.map +1 -1
- package/esm/errors/esbuild-binary-missing-error.mjs +1 -1
- package/esm/errors/esbuild-binary-missing-error.mjs.map +1 -1
- package/esm/errors/index.d.mts +2 -0
- package/esm/errors/index.mjs +3 -0
- package/esm/errors/unknown-locale-error.mjs +1 -1
- package/esm/errors/unknown-locale-error.mjs.map +1 -1
- package/esm/generations/add-command.action.mjs +29 -6
- package/esm/generations/add-command.action.mjs.map +1 -1
- package/esm/generations/features/access.feature.mjs +1 -1
- package/esm/generations/features/access.feature.mjs.map +1 -1
- package/esm/generations/features/ai-anthropic.feature.mjs +1 -1
- package/esm/generations/features/ai-anthropic.feature.mjs.map +1 -1
- package/esm/generations/features/ai-bedrock.feature.mjs +1 -1
- package/esm/generations/features/ai-bedrock.feature.mjs.map +1 -1
- package/esm/generations/features/ai-google.feature.mjs +1 -1
- package/esm/generations/features/ai-google.feature.mjs.map +1 -1
- package/esm/generations/features/ai-ollama.feature.mjs +1 -1
- package/esm/generations/features/ai-ollama.feature.mjs.map +1 -1
- package/esm/generations/features/ai-openai.feature.mjs +1 -1
- package/esm/generations/features/ai-openai.feature.mjs.map +1 -1
- package/esm/generations/features/ai-panoptic.feature.mjs +1 -1
- package/esm/generations/features/ai-panoptic.feature.mjs.map +1 -1
- package/esm/generations/features/ai-tools.feature.mjs +1 -1
- package/esm/generations/features/ai-tools.feature.mjs.map +1 -1
- package/esm/generations/features/ai-workspace.feature.mjs +1 -1
- package/esm/generations/features/ai-workspace.feature.mjs.map +1 -1
- package/esm/generations/features/ai.feature.mjs +1 -1
- package/esm/generations/features/ai.feature.mjs.map +1 -1
- package/esm/generations/features/auth-google.feature.mjs +1 -1
- package/esm/generations/features/auth-google.feature.mjs.map +1 -1
- package/esm/generations/features/auth-passkeys.feature.mjs +1 -1
- package/esm/generations/features/auth-passkeys.feature.mjs.map +1 -1
- package/esm/generations/features/bull-board.feature.mjs +1 -1
- package/esm/generations/features/bull-board.feature.mjs.map +1 -1
- package/esm/generations/features/devtools.feature.mjs +1 -1
- package/esm/generations/features/devtools.feature.mjs.map +1 -1
- package/esm/generations/features/herald.feature.mjs +1 -1
- package/esm/generations/features/herald.feature.mjs.map +1 -1
- package/esm/generations/features/image.feature.mjs +1 -1
- package/esm/generations/features/image.feature.mjs.map +1 -1
- package/esm/generations/features/index.mjs +1 -1
- package/esm/generations/features/index.mjs.map +1 -1
- package/esm/generations/features/mail.feature.mjs +1 -1
- package/esm/generations/features/mail.feature.mjs.map +1 -1
- package/esm/generations/features/mongodb.feature.mjs +1 -1
- package/esm/generations/features/mongodb.feature.mjs.map +1 -1
- package/esm/generations/features/mysql.feature.mjs +1 -1
- package/esm/generations/features/mysql.feature.mjs.map +1 -1
- package/esm/generations/features/notifications.feature.mjs +121 -17
- package/esm/generations/features/notifications.feature.mjs.map +1 -1
- package/esm/generations/features/postgres.feature.mjs +1 -1
- package/esm/generations/features/postgres.feature.mjs.map +1 -1
- package/esm/generations/features/queue.feature.mjs +1 -1
- package/esm/generations/features/queue.feature.mjs.map +1 -1
- package/esm/generations/features/react-email.feature.mjs +1 -1
- package/esm/generations/features/react-email.feature.mjs.map +1 -1
- package/esm/generations/features/react.feature.mjs +1 -1
- package/esm/generations/features/react.feature.mjs.map +1 -1
- package/esm/generations/features/redis.feature.mjs +1 -1
- package/esm/generations/features/redis.feature.mjs.map +1 -1
- package/esm/generations/features/s3.feature.mjs +1 -1
- package/esm/generations/features/s3.feature.mjs.map +1 -1
- package/esm/generations/features/scheduler.feature.mjs +1 -1
- package/esm/generations/features/scheduler.feature.mjs.map +1 -1
- package/esm/generations/features/ses.feature.mjs +1 -1
- package/esm/generations/features/ses.feature.mjs.map +1 -1
- package/esm/generations/features/shadcn.feature.mjs +1 -1
- package/esm/generations/features/shadcn.feature.mjs.map +1 -1
- package/esm/generations/features/shared/insert-connector-entry.mjs +1 -1
- package/esm/generations/features/shared/insert-connector-entry.mjs.map +1 -1
- package/esm/generations/features/shared/insert-queue-dashboard-block.mjs +1 -1
- package/esm/generations/features/shared/insert-queue-dashboard-block.mjs.map +1 -1
- package/esm/generations/features/shared/link-ai-package-import.mjs +1 -1
- package/esm/generations/features/shared/link-ai-package-import.mjs.map +1 -1
- package/esm/generations/features/shared/merge-web-sitemap-config.mjs +1 -1
- package/esm/generations/features/shared/merge-web-sitemap-config.mjs.map +1 -1
- package/esm/generations/features/shared/migration-timestamp.mjs +1 -1
- package/esm/generations/features/shared/migration-timestamp.mjs.map +1 -1
- package/esm/generations/features/shared/patch-tsconfig-include.mjs +1 -1
- package/esm/generations/features/shared/patch-tsconfig-include.mjs.map +1 -1
- package/esm/generations/features/shared/relocate-conflicting-home-route.mjs +1 -1
- package/esm/generations/features/shared/relocate-conflicting-home-route.mjs.map +1 -1
- package/esm/generations/features/shared/resolve-contact-scaffold.mjs +1 -1
- package/esm/generations/features/shared/resolve-contact-scaffold.mjs.map +1 -1
- package/esm/generations/features/sitemap.feature.mjs +1 -1
- package/esm/generations/features/sitemap.feature.mjs.map +1 -1
- package/esm/generations/features/socket.feature.mjs +1 -1
- package/esm/generations/features/socket.feature.mjs.map +1 -1
- package/esm/generations/features/tailwind.feature.mjs +1 -1
- package/esm/generations/features/tailwind.feature.mjs.map +1 -1
- package/esm/generations/features/test.feature.mjs +1 -1
- package/esm/generations/features/test.feature.mjs.map +1 -1
- package/esm/generations/features/types.mjs +1 -1
- package/esm/generations/features/types.mjs.map +1 -1
- package/esm/generations/features/web.feature.mjs +1 -1
- package/esm/generations/features/web.feature.mjs.map +1 -1
- package/esm/generations/pnpm-build-approvals.mjs +89 -3
- package/esm/generations/pnpm-build-approvals.mjs.map +1 -1
- package/esm/generations/stubs.mjs +184 -78
- package/esm/generations/stubs.mjs.map +1 -1
- package/esm/http/boot-port-preflight.d.mts +1 -1
- package/esm/http/boot-port-preflight.d.mts.map +1 -1
- package/esm/http/boot-port-preflight.mjs +1 -1
- package/esm/http/boot-port-preflight.mjs.map +1 -1
- package/esm/http/build-cors-options.mjs +1 -1
- package/esm/http/build-cors-options.mjs.map +1 -1
- package/esm/http/build-rate-limit-options.d.mts +22 -1
- package/esm/http/build-rate-limit-options.d.mts.map +1 -1
- package/esm/http/build-rate-limit-options.mjs +7 -1
- package/esm/http/build-rate-limit-options.mjs.map +1 -1
- package/esm/http/config.d.mts +1 -1
- package/esm/http/config.d.mts.map +1 -1
- package/esm/http/config.mjs +1 -1
- package/esm/http/config.mjs.map +1 -1
- package/esm/http/context/request-context.d.mts +1 -1
- package/esm/http/context/request-context.d.mts.map +1 -1
- package/esm/http/context/request-context.mjs +1 -1
- package/esm/http/context/request-context.mjs.map +1 -1
- package/esm/http/context/request-memo.d.mts +1 -1
- package/esm/http/context/request-memo.d.mts.map +1 -1
- package/esm/http/context/request-memo.mjs +1 -1
- package/esm/http/context/request-memo.mjs.map +1 -1
- package/esm/http/createHttpApplication.d.mts +1 -1
- package/esm/http/createHttpApplication.d.mts.map +1 -1
- package/esm/http/createHttpApplication.mjs +1 -1
- package/esm/http/createHttpApplication.mjs.map +1 -1
- package/esm/http/csp.d.mts +1 -1
- package/esm/http/csp.d.mts.map +1 -1
- package/esm/http/csp.mjs +1 -1
- package/esm/http/csp.mjs.map +1 -1
- package/esm/http/csrf-default-guard.d.mts +1 -1
- package/esm/http/csrf-default-guard.d.mts.map +1 -1
- package/esm/http/csrf-default-guard.mjs +1 -1
- package/esm/http/csrf-default-guard.mjs.map +1 -1
- package/esm/http/csrf-origin-policy.d.mts +1 -1
- package/esm/http/csrf-origin-policy.d.mts.map +1 -1
- package/esm/http/csrf-origin-policy.mjs +1 -1
- package/esm/http/csrf-origin-policy.mjs.map +1 -1
- package/esm/http/database/RequestLog.d.mts +63 -111
- package/esm/http/database/RequestLog.d.mts.map +1 -1
- package/esm/http/database/RequestLog.mjs +1 -1
- package/esm/http/database/RequestLog.mjs.map +1 -1
- package/esm/http/error-codes.d.mts +1 -1
- package/esm/http/error-codes.d.mts.map +1 -1
- package/esm/http/error-codes.mjs +1 -1
- package/esm/http/error-codes.mjs.map +1 -1
- package/esm/http/error-mapper.d.mts +48 -0
- package/esm/http/error-mapper.d.mts.map +1 -0
- package/esm/http/error-mapper.mjs +48 -0
- package/esm/http/error-mapper.mjs.map +1 -0
- package/esm/http/errors/errors.d.mts +1 -1
- package/esm/http/errors/errors.d.mts.map +1 -1
- package/esm/http/errors/errors.mjs +1 -1
- package/esm/http/errors/errors.mjs.map +1 -1
- package/esm/http/events.d.mts +1 -1
- package/esm/http/events.d.mts.map +1 -1
- package/esm/http/events.mjs +1 -1
- package/esm/http/events.mjs.map +1 -1
- package/esm/http/flush-pending-cookies.mjs +1 -1
- package/esm/http/flush-pending-cookies.mjs.map +1 -1
- package/esm/http/health.d.mts +1 -1
- package/esm/http/health.d.mts.map +1 -1
- package/esm/http/health.mjs +1 -1
- package/esm/http/health.mjs.map +1 -1
- package/esm/http/index.d.mts +10 -6
- package/esm/http/index.mjs +8 -5
- package/esm/http/middleware/cache-response-middleware.d.mts +1 -1
- package/esm/http/middleware/cache-response-middleware.d.mts.map +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs +1 -1
- package/esm/http/middleware/cache-response-middleware.mjs.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs +1 -1
- package/esm/http/middleware/concurrency-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts +1 -1
- package/esm/http/middleware/idempotency.middleware.d.mts.map +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs +1 -1
- package/esm/http/middleware/idempotency.middleware.mjs.map +1 -1
- package/esm/http/middleware/inject-request-context.d.mts +1 -1
- package/esm/http/middleware/inject-request-context.d.mts.map +1 -1
- package/esm/http/middleware/inject-request-context.mjs +4 -2
- package/esm/http/middleware/inject-request-context.mjs.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts +1 -1
- package/esm/http/middleware/ip-filter.middleware.d.mts.map +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs +1 -1
- package/esm/http/middleware/ip-filter.middleware.mjs.map +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts +1 -1
- package/esm/http/middleware/maintenance.middleware.d.mts.map +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs +1 -1
- package/esm/http/middleware/maintenance.middleware.mjs.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts +1 -1
- package/esm/http/middleware/max-body-size.middleware.d.mts.map +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs +1 -1
- package/esm/http/middleware/max-body-size.middleware.mjs.map +1 -1
- package/esm/http/middleware/middleware-list.d.mts +1 -1
- package/esm/http/middleware/middleware-list.d.mts.map +1 -1
- package/esm/http/middleware/middleware-list.mjs +1 -1
- package/esm/http/middleware/middleware-list.mjs.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.d.mts +20 -5
- package/esm/http/middleware/rate-limit.middleware.d.mts.map +1 -1
- package/esm/http/middleware/rate-limit.middleware.mjs +34 -12
- package/esm/http/middleware/rate-limit.middleware.mjs.map +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts +1 -1
- package/esm/http/middleware/utils/cidr-match.d.mts.map +1 -1
- package/esm/http/middleware/utils/cidr-match.mjs +1 -1
- package/esm/http/middleware/utils/cidr-match.mjs.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts +1 -1
- package/esm/http/middleware/utils/idempotency-key.d.mts.map +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs +1 -1
- package/esm/http/middleware/utils/idempotency-key.mjs.map +1 -1
- package/esm/http/middleware/utils/parse-size.d.mts +1 -1
- package/esm/http/middleware/utils/parse-size.d.mts.map +1 -1
- package/esm/http/middleware/utils/parse-size.mjs +1 -1
- package/esm/http/middleware/utils/parse-size.mjs.map +1 -1
- package/esm/http/parse-urlencoded-body.mjs +1 -1
- package/esm/http/parse-urlencoded-body.mjs.map +1 -1
- package/esm/http/plugins.d.mts +9 -2
- package/esm/http/plugins.d.mts.map +1 -1
- package/esm/http/plugins.mjs +18 -4
- package/esm/http/plugins.mjs.map +1 -1
- package/esm/http/port-preflight.d.mts +1 -1
- package/esm/http/port-preflight.d.mts.map +1 -1
- package/esm/http/port-preflight.mjs +1 -1
- package/esm/http/port-preflight.mjs.map +1 -1
- package/esm/http/rate-limit-cache-store.mjs +155 -0
- package/esm/http/rate-limit-cache-store.mjs.map +1 -0
- package/esm/http/ready-report.d.mts +1 -1
- package/esm/http/ready-report.d.mts.map +1 -1
- package/esm/http/ready-report.mjs +1 -1
- package/esm/http/ready-report.mjs.map +1 -1
- package/esm/http/request-controller.d.mts +1 -1
- package/esm/http/request-controller.d.mts.map +1 -1
- package/esm/http/request-controller.mjs +1 -1
- package/esm/http/request-controller.mjs.map +1 -1
- package/esm/http/request-log-snapshot.d.mts +123 -0
- package/esm/http/request-log-snapshot.d.mts.map +1 -0
- package/esm/http/request-log-snapshot.mjs +141 -0
- package/esm/http/request-log-snapshot.mjs.map +1 -0
- package/esm/http/request.d.mts +41 -2
- package/esm/http/request.d.mts.map +1 -1
- package/esm/http/request.mjs +65 -2
- package/esm/http/request.mjs.map +1 -1
- package/esm/http/resolve-bind-port.mjs +1 -1
- package/esm/http/resolve-bind-port.mjs.map +1 -1
- package/esm/http/response.d.mts +40 -8
- package/esm/http/response.d.mts.map +1 -1
- package/esm/http/response.mjs +173 -61
- package/esm/http/response.mjs.map +1 -1
- package/esm/http/serialized.d.mts +1 -1
- package/esm/http/serialized.d.mts.map +1 -1
- package/esm/http/server-rebuilt.d.mts +1 -1
- package/esm/http/server-rebuilt.d.mts.map +1 -1
- package/esm/http/server-rebuilt.mjs +1 -1
- package/esm/http/server-rebuilt.mjs.map +1 -1
- package/esm/http/server.d.mts +34 -6
- package/esm/http/server.d.mts.map +1 -1
- package/esm/http/server.mjs +70 -5
- package/esm/http/server.mjs.map +1 -1
- package/esm/http/stream-react-response.d.mts +1 -1
- package/esm/http/stream-react-response.d.mts.map +1 -1
- package/esm/http/stream-react-response.mjs +1 -1
- package/esm/http/stream-react-response.mjs.map +1 -1
- package/esm/http/stream-transport.mjs +75 -0
- package/esm/http/stream-transport.mjs.map +1 -0
- package/esm/http/tracing/trace-id.d.mts +1 -1
- package/esm/http/tracing/trace-id.d.mts.map +1 -1
- package/esm/http/tracing/trace-id.mjs +1 -1
- package/esm/http/tracing/trace-id.mjs.map +1 -1
- package/esm/http/tracing/tracing-dispatcher.d.mts +1 -1
- package/esm/http/tracing/tracing-dispatcher.d.mts.map +1 -1
- package/esm/http/tracing/tracing-dispatcher.mjs +1 -1
- package/esm/http/tracing/tracing-dispatcher.mjs.map +1 -1
- package/esm/http/tracing/tracing.type.d.mts +1 -1
- package/esm/http/tracing/tracing.type.d.mts.map +1 -1
- package/esm/http/types.d.mts +131 -6
- package/esm/http/types.d.mts.map +1 -1
- package/esm/http/uploaded-file.d.mts +2 -2
- package/esm/http/uploaded-file.d.mts.map +1 -1
- package/esm/http/uploaded-file.mjs +2 -2
- package/esm/http/uploaded-file.mjs.map +1 -1
- package/esm/http/uploads/detect-image-format.mjs +1 -1
- package/esm/http/uploads/detect-image-format.mjs.map +1 -1
- package/esm/http/uploads/generate-image-variant.mjs +1 -1
- package/esm/http/uploads/generate-image-variant.mjs.map +1 -1
- package/esm/http/uploads/generate-image-variants.d.mts +1 -1
- package/esm/http/uploads/generate-image-variants.d.mts.map +1 -1
- package/esm/http/uploads/generate-image-variants.mjs +15 -7
- package/esm/http/uploads/generate-image-variants.mjs.map +1 -1
- package/esm/http/uploads/image-variant-cache.mjs +143 -0
- package/esm/http/uploads/image-variant-cache.mjs.map +1 -0
- package/esm/http/uploads/image-variant-types.d.mts +1 -1
- package/esm/http/uploads/image-variant-types.d.mts.map +1 -1
- package/esm/http/uploads/image-variants-config-error.d.mts +1 -1
- package/esm/http/uploads/image-variants-config-error.d.mts.map +1 -1
- package/esm/http/uploads/image-variants-config-error.mjs +1 -1
- package/esm/http/uploads/image-variants-config-error.mjs.map +1 -1
- package/esm/http/uploads/index.d.mts +3 -1
- package/esm/http/uploads/index.mjs +3 -1
- package/esm/http/uploads/is-path-inside.mjs +1 -1
- package/esm/http/uploads/is-path-inside.mjs.map +1 -1
- package/esm/http/uploads/load-variant-source.mjs +1 -1
- package/esm/http/uploads/load-variant-source.mjs.map +1 -1
- package/esm/http/uploads/local-disk-root.mjs +24 -0
- package/esm/http/uploads/local-disk-root.mjs.map +1 -0
- package/esm/http/uploads/matches-if-none-match.mjs +1 -1
- package/esm/http/uploads/matches-if-none-match.mjs.map +1 -1
- package/esm/http/uploads/parse-uploaded-file-query.mjs +1 -1
- package/esm/http/uploads/parse-uploaded-file-query.mjs.map +1 -1
- package/esm/http/uploads/purge-image-variants.d.mts +32 -0
- package/esm/http/uploads/purge-image-variants.d.mts.map +1 -0
- package/esm/http/uploads/purge-image-variants.mjs +46 -0
- package/esm/http/uploads/purge-image-variants.mjs.map +1 -0
- package/esm/http/uploads/read-file-head.mjs +1 -1
- package/esm/http/uploads/read-file-head.mjs.map +1 -1
- package/esm/http/uploads/resolve-image-variant.d.mts +73 -0
- package/esm/http/uploads/resolve-image-variant.d.mts.map +1 -0
- package/esm/http/uploads/resolve-image-variant.mjs +107 -0
- package/esm/http/uploads/resolve-image-variant.mjs.map +1 -0
- package/esm/http/uploads/resolve-image-variants-config.mjs +1 -1
- package/esm/http/uploads/resolve-image-variants-config.mjs.map +1 -1
- package/esm/http/uploads/resolve-inline-image-content-type.mjs +1 -1
- package/esm/http/uploads/resolve-inline-image-content-type.mjs.map +1 -1
- package/esm/http/uploads/resolve-original-content-type.mjs +1 -1
- package/esm/http/uploads/resolve-original-content-type.mjs.map +1 -1
- package/esm/http/uploads/resolve-upload-path.mjs +3 -2
- package/esm/http/uploads/resolve-upload-path.mjs.map +1 -1
- package/esm/http/uploads/resolve-variant-candidate.mjs +1 -1
- package/esm/http/uploads/resolve-variant-candidate.mjs.map +1 -1
- package/esm/http/uploads/single-flight.mjs +1 -1
- package/esm/http/uploads/single-flight.mjs.map +1 -1
- package/esm/http/uploads/uploaded-file.controller.d.mts +24 -6
- package/esm/http/uploads/uploaded-file.controller.d.mts.map +1 -1
- package/esm/http/uploads/uploaded-file.controller.mjs +63 -91
- package/esm/http/uploads/uploaded-file.controller.mjs.map +1 -1
- package/esm/http/uploads/variant-cache-key.mjs +30 -5
- package/esm/http/uploads/variant-cache-key.mjs.map +1 -1
- package/esm/http/uploads/variant-generations.mjs +1 -1
- package/esm/http/uploads/variant-generations.mjs.map +1 -1
- package/esm/http/uploads-config.d.mts +1 -1
- package/esm/http/uploads-config.d.mts.map +1 -1
- package/esm/http/uploads-config.mjs +1 -1
- package/esm/http/uploads-config.mjs.map +1 -1
- package/esm/http/uploads-types.d.mts +1 -1
- package/esm/http/uploads-types.d.mts.map +1 -1
- package/esm/http/xmlable.d.mts +1 -1
- package/esm/http/xmlable.d.mts.map +1 -1
- package/esm/image/image.d.mts +1 -1
- package/esm/image/image.d.mts.map +1 -1
- package/esm/image/image.mjs +1 -1
- package/esm/image/image.mjs.map +1 -1
- package/esm/index.d.mts +13 -9
- package/esm/index.mjs +10 -7
- package/esm/loader/app-module-importer.d.mts +1 -1
- package/esm/loader/app-module-importer.d.mts.map +1 -1
- package/esm/loader/app-module-importer.mjs +1 -1
- package/esm/loader/app-module-importer.mjs.map +1 -1
- package/esm/localization/parse-locale-dictionary.d.mts +1 -1
- package/esm/localization/parse-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/parse-locale-dictionary.mjs +1 -1
- package/esm/localization/parse-locale-dictionary.mjs.map +1 -1
- package/esm/localization/register-locale-dictionary.d.mts +1 -1
- package/esm/localization/register-locale-dictionary.d.mts.map +1 -1
- package/esm/localization/register-locale-dictionary.mjs +1 -1
- package/esm/localization/register-locale-dictionary.mjs.map +1 -1
- package/esm/logger/fatal-visibility.d.mts +1 -1
- package/esm/logger/fatal-visibility.d.mts.map +1 -1
- package/esm/logger/fatal-visibility.mjs +1 -1
- package/esm/logger/fatal-visibility.mjs.map +1 -1
- package/esm/logger/logger.d.mts +1 -1
- package/esm/logger/logger.d.mts.map +1 -1
- package/esm/logger/logger.mjs +1 -1
- package/esm/logger/logger.mjs.map +1 -1
- package/esm/logger/types.d.mts +1 -1
- package/esm/logger/types.d.mts.map +1 -1
- package/esm/mail/config.d.mts +1 -1
- package/esm/mail/config.d.mts.map +1 -1
- package/esm/mail/config.mjs +1 -1
- package/esm/mail/config.mjs.map +1 -1
- package/esm/mail/events.d.mts +1 -1
- package/esm/mail/events.d.mts.map +1 -1
- package/esm/mail/events.mjs +1 -1
- package/esm/mail/events.mjs.map +1 -1
- package/esm/mail/mail.d.mts +1 -1
- package/esm/mail/mail.d.mts.map +1 -1
- package/esm/mail/mail.mjs +1 -1
- package/esm/mail/mail.mjs.map +1 -1
- package/esm/mail/mailer-pool.d.mts +1 -1
- package/esm/mail/mailer-pool.d.mts.map +1 -1
- package/esm/mail/mailer-pool.mjs +1 -1
- package/esm/mail/mailer-pool.mjs.map +1 -1
- package/esm/mail/react-mail.d.mts +1 -1
- package/esm/mail/react-mail.d.mts.map +1 -1
- package/esm/mail/react-mail.mjs +1 -1
- package/esm/mail/react-mail.mjs.map +1 -1
- package/esm/mail/send-mail.d.mts +1 -1
- package/esm/mail/send-mail.d.mts.map +1 -1
- package/esm/mail/send-mail.mjs +7 -7
- package/esm/mail/send-mail.mjs.map +1 -1
- package/esm/mail/test-mailbox.d.mts +1 -1
- package/esm/mail/test-mailbox.d.mts.map +1 -1
- package/esm/mail/test-mailbox.mjs +1 -1
- package/esm/mail/test-mailbox.mjs.map +1 -1
- package/esm/mail/types.d.mts +1 -1
- package/esm/mail/types.d.mts.map +1 -1
- package/esm/mail/types.mjs +1 -1
- package/esm/mail/types.mjs.map +1 -1
- package/esm/manifest/manifest-manager.mjs +1 -1
- package/esm/manifest/manifest-manager.mjs.map +1 -1
- package/esm/openapi/build-openapi-document.d.mts +1 -1
- package/esm/openapi/build-openapi-document.d.mts.map +1 -1
- package/esm/openapi/build-openapi-document.mjs +1 -1
- package/esm/openapi/build-openapi-document.mjs.map +1 -1
- package/esm/openapi/cast-schema.mjs +1 -1
- package/esm/openapi/cast-schema.mjs.map +1 -1
- package/esm/openapi/collect-openapi-document.mjs +1 -1
- package/esm/openapi/collect-openapi-document.mjs.map +1 -1
- package/esm/openapi/development-openapi-provider.d.mts +1 -1
- package/esm/openapi/development-openapi-provider.d.mts.map +1 -1
- package/esm/openapi/development-openapi-provider.mjs +1 -1
- package/esm/openapi/development-openapi-provider.mjs.map +1 -1
- package/esm/openapi/error-responses.mjs +1 -1
- package/esm/openapi/error-responses.mjs.map +1 -1
- package/esm/openapi/openapi-child-output.mjs +1 -1
- package/esm/openapi/openapi-child-output.mjs.map +1 -1
- package/esm/openapi/openapi-protocol.mjs +1 -1
- package/esm/openapi/openapi-protocol.mjs.map +1 -1
- package/esm/openapi/paths.mjs +1 -1
- package/esm/openapi/paths.mjs.map +1 -1
- package/esm/openapi/postman/build-request-body.mjs +1 -1
- package/esm/openapi/postman/build-request-body.mjs.map +1 -1
- package/esm/openapi/postman/build-request-url.mjs +1 -1
- package/esm/openapi/postman/build-request-url.mjs.map +1 -1
- package/esm/openapi/postman/build-saved-responses.mjs +1 -1
- package/esm/openapi/postman/build-saved-responses.mjs.map +1 -1
- package/esm/openapi/postman/example-from-schema.d.mts +1 -1
- package/esm/openapi/postman/example-from-schema.d.mts.map +1 -1
- package/esm/openapi/postman/example-from-schema.mjs +1 -1
- package/esm/openapi/postman/example-from-schema.mjs.map +1 -1
- package/esm/openapi/postman/http-status-text.mjs +1 -1
- package/esm/openapi/postman/http-status-text.mjs.map +1 -1
- package/esm/openapi/postman/openapi-to-postman-collection.d.mts +1 -1
- package/esm/openapi/postman/openapi-to-postman-collection.d.mts.map +1 -1
- package/esm/openapi/postman/openapi-to-postman-collection.mjs +1 -1
- package/esm/openapi/postman/openapi-to-postman-collection.mjs.map +1 -1
- package/esm/openapi/postman/postman-types.d.mts +1 -1
- package/esm/openapi/postman/postman-types.d.mts.map +1 -1
- package/esm/openapi/postman/resolve-operation-auth.mjs +1 -1
- package/esm/openapi/postman/resolve-operation-auth.mjs.map +1 -1
- package/esm/openapi/postman/schema-refs.d.mts +1 -1
- package/esm/openapi/postman/schema-refs.d.mts.map +1 -1
- package/esm/openapi/postman/schema-refs.mjs +1 -1
- package/esm/openapi/postman/schema-refs.mjs.map +1 -1
- package/esm/openapi/postman/uuid-v5.mjs +1 -1
- package/esm/openapi/postman/uuid-v5.mjs.map +1 -1
- package/esm/openapi/request-schemas.mjs +1 -1
- package/esm/openapi/request-schemas.mjs.map +1 -1
- package/esm/openapi/response-schemas.mjs +1 -1
- package/esm/openapi/response-schemas.mjs.map +1 -1
- package/esm/openapi/schema-registry.mjs +1 -1
- package/esm/openapi/schema-registry.mjs.map +1 -1
- package/esm/openapi/security.mjs +1 -1
- package/esm/openapi/security.mjs.map +1 -1
- package/esm/openapi/types.d.mts +1 -1
- package/esm/openapi/types.d.mts.map +1 -1
- package/esm/production/assert-dist-ready-to-start.mjs +1 -1
- package/esm/production/assert-dist-ready-to-start.mjs.map +1 -1
- package/esm/production/assert-generated-imports.mjs +1 -1
- package/esm/production/assert-generated-imports.mjs.map +1 -1
- package/esm/production/build-app-production.mjs +1 -1
- package/esm/production/build-app-production.mjs.map +1 -1
- package/esm/production/build-contributions.mjs +1 -1
- package/esm/production/build-contributions.mjs.map +1 -1
- package/esm/production/bundle-framework-dependencies.mjs +1 -1
- package/esm/production/bundle-framework-dependencies.mjs.map +1 -1
- package/esm/production/dist-build-manifest.mjs +1 -1
- package/esm/production/dist-build-manifest.mjs.map +1 -1
- package/esm/production/esbuild-plugins.mjs +1 -1
- package/esm/production/esbuild-plugins.mjs.map +1 -1
- package/esm/production/esbuild-preflight.mjs +1 -1
- package/esm/production/esbuild-preflight.mjs.map +1 -1
- package/esm/production/production-builder.mjs +1 -1
- package/esm/production/production-builder.mjs.map +1 -1
- package/esm/production/production-supervisor.mjs +1 -1
- package/esm/production/production-supervisor.mjs.map +1 -1
- package/esm/production/promote-dist.mjs +1 -1
- package/esm/production/promote-dist.mjs.map +1 -1
- package/esm/production/registration-child-runner.mjs +1 -1
- package/esm/production/registration-child-runner.mjs.map +1 -1
- package/esm/production/resolve-build-config.d.mts +1 -1
- package/esm/production/resolve-build-config.d.mts.map +1 -1
- package/esm/production/resolve-build-config.mjs +1 -1
- package/esm/production/resolve-build-config.mjs.map +1 -1
- package/esm/production/route-registration-child.mjs +1 -1
- package/esm/production/route-registration-child.mjs.map +1 -1
- package/esm/production/route-registration-snapshot.mjs +1 -1
- package/esm/production/route-registration-snapshot.mjs.map +1 -1
- package/esm/production/tsconfig-path-aliases.mjs +1 -1
- package/esm/production/tsconfig-path-aliases.mjs.map +1 -1
- package/esm/react/index.d.mts +1 -1
- package/esm/react/index.d.mts.map +1 -1
- package/esm/react/index.mjs +1 -1
- package/esm/react/index.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.mjs +1 -1
- package/esm/repositories/adapters/cascade/cascade-adapter.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.d.mts.map +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs +1 -1
- package/esm/repositories/adapters/cascade/cascade-query-builder.mjs.map +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs +1 -1
- package/esm/repositories/adapters/cascade/filter-applicator.mjs.map +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts +1 -1
- package/esm/repositories/contracts/query-builder.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts +1 -1
- package/esm/repositories/contracts/repository-adapter.contract.d.mts.map +1 -1
- package/esm/repositories/contracts/types.d.mts +1 -1
- package/esm/repositories/contracts/types.d.mts.map +1 -1
- package/esm/repositories/repository.manager.d.mts +1 -1
- package/esm/repositories/repository.manager.d.mts.map +1 -1
- package/esm/repositories/repository.manager.mjs +1 -1
- package/esm/repositories/repository.manager.mjs.map +1 -1
- package/esm/resource/define-resource.d.mts +1 -1
- package/esm/resource/define-resource.d.mts.map +1 -1
- package/esm/resource/define-resource.mjs +1 -1
- package/esm/resource/define-resource.mjs.map +1 -1
- package/esm/resource/nullable-resource.d.mts +1 -1
- package/esm/resource/nullable-resource.d.mts.map +1 -1
- package/esm/resource/nullable-resource.mjs +1 -1
- package/esm/resource/nullable-resource.mjs.map +1 -1
- package/esm/resource/register-resource.d.mts +1 -1
- package/esm/resource/register-resource.d.mts.map +1 -1
- package/esm/resource/register-resource.mjs +1 -1
- package/esm/resource/register-resource.mjs.map +1 -1
- package/esm/resource/resource-field-builder.d.mts +1 -1
- package/esm/resource/resource-field-builder.d.mts.map +1 -1
- package/esm/resource/resource-field-builder.mjs +1 -1
- package/esm/resource/resource-field-builder.mjs.map +1 -1
- package/esm/resource/resource.d.mts +1 -1
- package/esm/resource/resource.d.mts.map +1 -1
- package/esm/resource/resource.mjs +1 -1
- package/esm/resource/resource.mjs.map +1 -1
- package/esm/resource/types.d.mts +1 -1
- package/esm/resource/types.d.mts.map +1 -1
- package/esm/restful/restful.d.mts +1 -1
- package/esm/restful/restful.d.mts.map +1 -1
- package/esm/restful/restful.mjs +1 -1
- package/esm/restful/restful.mjs.map +1 -1
- package/esm/router/build-route-rate-limit.mjs +1 -1
- package/esm/router/build-route-rate-limit.mjs.map +1 -1
- package/esm/router/describe-route-for-log.mjs +1 -1
- package/esm/router/describe-route-for-log.mjs.map +1 -1
- package/esm/router/dev-dispatch.mjs +1 -1
- package/esm/router/dev-dispatch.mjs.map +1 -1
- package/esm/router/log-request-lifecycle.mjs +1 -1
- package/esm/router/log-request-lifecycle.mjs.map +1 -1
- package/esm/router/named-api-routes-with-responses.mjs +1 -1
- package/esm/router/named-api-routes-with-responses.mjs.map +1 -1
- package/esm/router/normalize-request-path.d.mts +1 -1
- package/esm/router/normalize-request-path.d.mts.map +1 -1
- package/esm/router/normalize-request-path.mjs +1 -1
- package/esm/router/normalize-request-path.mjs.map +1 -1
- package/esm/router/normalize-route-path.d.mts +1 -1
- package/esm/router/normalize-route-path.d.mts.map +1 -1
- package/esm/router/normalize-route-path.mjs +1 -1
- package/esm/router/normalize-route-path.mjs.map +1 -1
- package/esm/router/positional-handler-diagnostics.d.mts +1 -1
- package/esm/router/positional-handler-diagnostics.d.mts.map +1 -1
- package/esm/router/positional-handler-diagnostics.mjs +1 -1
- package/esm/router/positional-handler-diagnostics.mjs.map +1 -1
- package/esm/router/response-schema-types.mjs +1 -1
- package/esm/router/response-schema-types.mjs.map +1 -1
- package/esm/router/route-builder.d.mts +1 -1
- package/esm/router/route-builder.d.mts.map +1 -1
- package/esm/router/route-builder.mjs +1 -1
- package/esm/router/route-builder.mjs.map +1 -1
- package/esm/router/route-name-method-suffix.d.mts +1 -1
- package/esm/router/route-name-method-suffix.d.mts.map +1 -1
- package/esm/router/route-name-method-suffix.mjs +1 -1
- package/esm/router/route-name-method-suffix.mjs.map +1 -1
- package/esm/router/route-registry.d.mts +1 -1
- package/esm/router/route-registry.d.mts.map +1 -1
- package/esm/router/route-registry.mjs +1 -1
- package/esm/router/route-registry.mjs.map +1 -1
- package/esm/router/router.d.mts +8 -1
- package/esm/router/router.d.mts.map +1 -1
- package/esm/router/router.mjs +20 -15
- package/esm/router/router.mjs.map +1 -1
- package/esm/router/types.d.mts +13 -1
- package/esm/router/types.d.mts.map +1 -1
- package/esm/socket/types.d.mts +1 -1
- package/esm/socket/types.d.mts.map +1 -1
- package/esm/socket/utils.d.mts +1 -1
- package/esm/socket/utils.d.mts.map +1 -1
- package/esm/socket/utils.mjs +1 -1
- package/esm/socket/utils.mjs.map +1 -1
- package/esm/storage/config.d.mts +1 -1
- package/esm/storage/config.d.mts.map +1 -1
- package/esm/storage/config.mjs +1 -1
- package/esm/storage/config.mjs.map +1 -1
- package/esm/storage/context/storage-driver-context.d.mts +1 -1
- package/esm/storage/context/storage-driver-context.d.mts.map +1 -1
- package/esm/storage/context/storage-driver-context.mjs +1 -1
- package/esm/storage/context/storage-driver-context.mjs.map +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts +1 -1
- package/esm/storage/drivers/cloud-driver.d.mts.map +1 -1
- package/esm/storage/drivers/cloud-driver.mjs +1 -1
- package/esm/storage/drivers/cloud-driver.mjs.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts +1 -1
- package/esm/storage/drivers/do-spaces-driver.d.mts.map +1 -1
- package/esm/storage/drivers/do-spaces-driver.mjs +1 -1
- package/esm/storage/drivers/do-spaces-driver.mjs.map +1 -1
- package/esm/storage/drivers/local-driver.d.mts +12 -1
- package/esm/storage/drivers/local-driver.d.mts.map +1 -1
- package/esm/storage/drivers/local-driver.mjs +33 -1
- package/esm/storage/drivers/local-driver.mjs.map +1 -1
- package/esm/storage/drivers/r2-driver.d.mts +1 -1
- package/esm/storage/drivers/r2-driver.d.mts.map +1 -1
- package/esm/storage/drivers/r2-driver.mjs +1 -1
- package/esm/storage/drivers/r2-driver.mjs.map +1 -1
- package/esm/storage/drivers/s3-driver.d.mts +1 -1
- package/esm/storage/drivers/s3-driver.d.mts.map +1 -1
- package/esm/storage/drivers/s3-driver.mjs +1 -1
- package/esm/storage/drivers/s3-driver.mjs.map +1 -1
- package/esm/storage/index.d.mts +1 -1
- package/esm/storage/scoped-storage.d.mts +1 -1
- package/esm/storage/scoped-storage.d.mts.map +1 -1
- package/esm/storage/scoped-storage.mjs +1 -1
- package/esm/storage/scoped-storage.mjs.map +1 -1
- package/esm/storage/storage-file.d.mts +1 -1
- package/esm/storage/storage-file.d.mts.map +1 -1
- package/esm/storage/storage-file.mjs +1 -1
- package/esm/storage/storage-file.mjs.map +1 -1
- package/esm/storage/storage.d.mts +3 -3
- package/esm/storage/storage.d.mts.map +1 -1
- package/esm/storage/storage.mjs +1 -1
- package/esm/storage/storage.mjs.map +1 -1
- package/esm/storage/types.d.mts +3 -2
- package/esm/storage/types.d.mts.map +1 -1
- package/esm/storage/utils/classify-ip-address.d.mts +1 -1
- package/esm/storage/utils/classify-ip-address.d.mts.map +1 -1
- package/esm/storage/utils/classify-ip-address.mjs +1 -1
- package/esm/storage/utils/classify-ip-address.mjs.map +1 -1
- package/esm/storage/utils/contain-path.d.mts +1 -1
- package/esm/storage/utils/contain-path.d.mts.map +1 -1
- package/esm/storage/utils/contain-path.mjs +1 -1
- package/esm/storage/utils/contain-path.mjs.map +1 -1
- package/esm/storage/utils/mime.d.mts +1 -1
- package/esm/storage/utils/mime.d.mts.map +1 -1
- package/esm/storage/utils/mime.mjs +1 -1
- package/esm/storage/utils/mime.mjs.map +1 -1
- package/esm/storage/utils/safe-fetch.d.mts +1 -1
- package/esm/storage/utils/safe-fetch.d.mts.map +1 -1
- package/esm/storage/utils/safe-fetch.mjs +1 -1
- package/esm/storage/utils/safe-fetch.mjs.map +1 -1
- package/esm/storage/utils/storage-capability-error.d.mts +1 -1
- package/esm/storage/utils/storage-capability-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-capability-error.mjs +1 -1
- package/esm/storage/utils/storage-capability-error.mjs.map +1 -1
- package/esm/storage/utils/storage-error.d.mts +1 -1
- package/esm/storage/utils/storage-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-error.mjs +1 -1
- package/esm/storage/utils/storage-error.mjs.map +1 -1
- package/esm/storage/utils/storage-not-initialized-error.d.mts +1 -1
- package/esm/storage/utils/storage-not-initialized-error.d.mts.map +1 -1
- package/esm/storage/utils/storage-not-initialized-error.mjs +1 -1
- package/esm/storage/utils/storage-not-initialized-error.mjs.map +1 -1
- package/esm/tests/start-http-development-server.d.mts +1 -1
- package/esm/tests/start-http-development-server.d.mts.map +1 -1
- package/esm/tests/start-http-development-server.mjs +1 -1
- package/esm/tests/start-http-development-server.mjs.map +1 -1
- package/esm/tests/test-connectors-selection.d.mts +1 -1
- package/esm/tests/test-connectors-selection.d.mts.map +1 -1
- package/esm/tests/test-connectors-selection.mjs +1 -1
- package/esm/tests/test-connectors-selection.mjs.map +1 -1
- package/esm/tests/test-helpers.d.mts +1 -1
- package/esm/tests/test-helpers.d.mts.map +1 -1
- package/esm/tests/test-helpers.mjs +1 -1
- package/esm/tests/test-helpers.mjs.map +1 -1
- package/esm/tests/test-lifecycle-state.mjs +1 -1
- package/esm/tests/test-lifecycle-state.mjs.map +1 -1
- package/esm/tests/test-server-port-channel.mjs +1 -1
- package/esm/tests/test-server-port-channel.mjs.map +1 -1
- package/esm/tests/test-setup-timeout.mjs +1 -1
- package/esm/tests/test-setup-timeout.mjs.map +1 -1
- package/esm/tests/vitest-setup.d.mts +1 -1
- package/esm/tests/vitest-setup.d.mts.map +1 -1
- package/esm/tests/vitest-setup.mjs +1 -1
- package/esm/tests/vitest-setup.mjs.map +1 -1
- package/esm/updater/package-manager.mjs +1 -1
- package/esm/updater/package-manager.mjs.map +1 -1
- package/esm/updater/update-warlock-packages.mjs +1 -1
- package/esm/updater/update-warlock-packages.mjs.map +1 -1
- package/esm/use-cases/types.d.mts +1 -1
- package/esm/use-cases/types.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts +1 -1
- package/esm/use-cases/use-case-broadcast.d.mts.map +1 -1
- package/esm/use-cases/use-case-broadcast.mjs +1 -1
- package/esm/use-cases/use-case-broadcast.mjs.map +1 -1
- package/esm/use-cases/use-case-events.d.mts +1 -1
- package/esm/use-cases/use-case-events.d.mts.map +1 -1
- package/esm/use-cases/use-case-events.mjs +1 -1
- package/esm/use-cases/use-case-events.mjs.map +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts +1 -1
- package/esm/use-cases/use-case-pipeline.d.mts.map +1 -1
- package/esm/use-cases/use-case-pipeline.mjs +1 -1
- package/esm/use-cases/use-case-pipeline.mjs.map +1 -1
- package/esm/use-cases/use-case.d.mts +1 -1
- package/esm/use-cases/use-case.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.d.mts +1 -1
- package/esm/use-cases/use-case.errors.d.mts.map +1 -1
- package/esm/use-cases/use-case.errors.mjs +1 -1
- package/esm/use-cases/use-case.errors.mjs.map +1 -1
- package/esm/use-cases/use-case.mjs +1 -1
- package/esm/use-cases/use-case.mjs.map +1 -1
- package/esm/use-cases/use-cases-registry.d.mts +1 -1
- package/esm/use-cases/use-cases-registry.d.mts.map +1 -1
- package/esm/use-cases/use-cases-registry.mjs +1 -1
- package/esm/use-cases/use-cases-registry.mjs.map +1 -1
- package/esm/utils/app-log.d.mts +6 -6
- package/esm/utils/app-log.d.mts.map +1 -1
- package/esm/utils/app-log.mjs +1 -1
- package/esm/utils/app-log.mjs.map +1 -1
- package/esm/utils/database-log.d.mts +1 -1
- package/esm/utils/database-log.d.mts.map +1 -1
- package/esm/utils/database-log.mjs +1 -1
- package/esm/utils/database-log.mjs.map +1 -1
- package/esm/utils/detect-environment-overrides.mjs +1 -1
- package/esm/utils/detect-environment-overrides.mjs.map +1 -1
- package/esm/utils/environment.d.mts +1 -1
- package/esm/utils/environment.d.mts.map +1 -1
- package/esm/utils/environment.mjs +1 -1
- package/esm/utils/environment.mjs.map +1 -1
- package/esm/utils/framework-vesion.mjs +1 -1
- package/esm/utils/framework-vesion.mjs.map +1 -1
- package/esm/utils/get-localized.d.mts +1 -1
- package/esm/utils/get-localized.d.mts.map +1 -1
- package/esm/utils/get-localized.mjs +1 -1
- package/esm/utils/get-localized.mjs.map +1 -1
- package/esm/utils/is-test-file.mjs +1 -1
- package/esm/utils/is-test-file.mjs.map +1 -1
- package/esm/utils/load-environment.mjs +1 -1
- package/esm/utils/load-environment.mjs.map +1 -1
- package/esm/utils/normalized-path.d.mts +1 -1
- package/esm/utils/normalized-path.d.mts.map +1 -1
- package/esm/utils/normalized-path.mjs +1 -1
- package/esm/utils/normalized-path.mjs.map +1 -1
- package/esm/utils/npm-registry.d.mts +1 -1
- package/esm/utils/npm-registry.d.mts.map +1 -1
- package/esm/utils/npm-registry.mjs +1 -1
- package/esm/utils/npm-registry.mjs.map +1 -1
- package/esm/utils/paths.d.mts +1 -1
- package/esm/utils/paths.d.mts.map +1 -1
- package/esm/utils/paths.mjs +1 -1
- package/esm/utils/paths.mjs.map +1 -1
- package/esm/utils/promise-all-object.d.mts +1 -1
- package/esm/utils/promise-all-object.d.mts.map +1 -1
- package/esm/utils/promise-all-object.mjs +1 -1
- package/esm/utils/promise-all-object.mjs.map +1 -1
- package/esm/utils/queue.d.mts +1 -1
- package/esm/utils/queue.d.mts.map +1 -1
- package/esm/utils/queue.mjs +1 -1
- package/esm/utils/queue.mjs.map +1 -1
- package/esm/utils/recorded-environment-overrides.mjs +1 -1
- package/esm/utils/recorded-environment-overrides.mjs.map +1 -1
- package/esm/utils/report-environment-overrides.mjs +1 -1
- package/esm/utils/report-environment-overrides.mjs.map +1 -1
- package/esm/utils/sleep.d.mts +1 -1
- package/esm/utils/sleep.d.mts.map +1 -1
- package/esm/utils/sleep.mjs +1 -1
- package/esm/utils/sleep.mjs.map +1 -1
- package/esm/utils/sluggable.d.mts +1 -1
- package/esm/utils/sluggable.d.mts.map +1 -1
- package/esm/utils/sluggable.mjs +1 -1
- package/esm/utils/sluggable.mjs.map +1 -1
- package/esm/utils/to-json.d.mts +1 -1
- package/esm/utils/to-json.d.mts.map +1 -1
- package/esm/utils/to-json.mjs +1 -1
- package/esm/utils/to-json.mjs.map +1 -1
- package/esm/utils/types.d.mts +1 -1
- package/esm/utils/types.d.mts.map +1 -1
- package/esm/utils/urls.d.mts +1 -1
- package/esm/utils/urls.d.mts.map +1 -1
- package/esm/utils/urls.mjs +1 -1
- package/esm/utils/urls.mjs.map +1 -1
- package/esm/utils/version-compare.d.mts +1 -1
- package/esm/utils/version-compare.d.mts.map +1 -1
- package/esm/utils/version-compare.mjs +1 -1
- package/esm/utils/version-compare.mjs.map +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts +1 -1
- package/esm/validation/database/exists-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-id.mjs +1 -1
- package/esm/validation/database/exists-except-current-id.mjs.map +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts +1 -1
- package/esm/validation/database/exists-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/exists-except-current-user.mjs +1 -1
- package/esm/validation/database/exists-except-current-user.mjs.map +1 -1
- package/esm/validation/database/types.d.mts +1 -1
- package/esm/validation/database/types.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts +1 -1
- package/esm/validation/database/unique-except-current-id.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-id.mjs +1 -1
- package/esm/validation/database/unique-except-current-id.mjs.map +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts +1 -1
- package/esm/validation/database/unique-except-current-user.d.mts.map +1 -1
- package/esm/validation/database/unique-except-current-user.mjs +1 -1
- package/esm/validation/database/unique-except-current-user.mjs.map +1 -1
- package/esm/validation/file/file.d.mts +1 -1
- package/esm/validation/file/file.d.mts.map +1 -1
- package/esm/validation/file/file.mjs +1 -1
- package/esm/validation/file/file.mjs.map +1 -1
- package/esm/validation/init.mjs +1 -1
- package/esm/validation/init.mjs.map +1 -1
- package/esm/validation/plugins/database-plugin.mjs +1 -1
- package/esm/validation/plugins/database-plugin.mjs.map +1 -1
- package/esm/validation/plugins/file-plugin.mjs +1 -1
- package/esm/validation/plugins/file-plugin.mjs.map +1 -1
- package/esm/validation/plugins/localized-plugin.mjs +1 -1
- package/esm/validation/plugins/localized-plugin.mjs.map +1 -1
- package/esm/validation/types.d.mts +1 -1
- package/esm/validation/types.d.mts.map +1 -1
- package/esm/validation/validateAll.mjs +1 -1
- package/esm/validation/validateAll.mjs.map +1 -1
- package/esm/validation/validators/file-validator.d.mts +44 -41
- package/esm/validation/validators/file-validator.d.mts.map +1 -1
- package/esm/validation/validators/file-validator.mjs +4 -1
- package/esm/validation/validators/file-validator.mjs.map +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts +1 -1
- package/esm/vite/lower-stage3-decorators.d.mts.map +1 -1
- package/esm/vite/lower-stage3-decorators.mjs +1 -1
- package/esm/vite/lower-stage3-decorators.mjs.map +1 -1
- package/esm/warlock-config/bundle-config.mjs +148 -0
- package/esm/warlock-config/bundle-config.mjs.map +1 -0
- package/esm/warlock-config/default-configurations.mjs +1 -1
- package/esm/warlock-config/default-configurations.mjs.map +1 -1
- package/esm/warlock-config/define-config.d.mts +1 -1
- package/esm/warlock-config/define-config.d.mts.map +1 -1
- package/esm/warlock-config/define-config.mjs +1 -1
- package/esm/warlock-config/define-config.mjs.map +1 -1
- package/esm/warlock-config/index.d.mts +1 -1
- package/esm/warlock-config/index.mjs +1 -1
- package/esm/warlock-config/normalize-build-config.mjs +1 -1
- package/esm/warlock-config/normalize-build-config.mjs.map +1 -1
- package/esm/warlock-config/types.d.mts +1 -1
- package/esm/warlock-config/types.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.d.mts +32 -7
- package/esm/warlock-config/warlock-config.manager.d.mts.map +1 -1
- package/esm/warlock-config/warlock-config.manager.mjs +94 -18
- package/esm/warlock-config/warlock-config.manager.mjs.map +1 -1
- package/esm/warlock-config/warn-deprecated-config.mjs +1 -1
- package/esm/warlock-config/warn-deprecated-config.mjs.map +1 -1
- package/llms-full.txt +66 -9
- package/package.json +20 -13
- package/skills/configure-app/SKILL.md +23 -1
- package/skills/create-controller/SKILL.md +4 -0
- package/skills/health-checks/SKILL.md +2 -0
- package/skills/register-route/SKILL.md +10 -0
- package/skills/run-app/SKILL.md +9 -2
- package/skills/send-response/SKILL.md +10 -2
- package/skills/store-file/SKILL.md +5 -1
- package/skills/use-middleware/SKILL.md +2 -2
- package/skills/validate-input/SKILL.md +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cloud-driver.mjs","names":[],"sources":["../../../../../../../../core/src/storage/drivers/cloud-driver.ts"],"sourcesContent":["import crypto from \"crypto\";\nimport { createRequire } from \"module\";\nimport type { Readable } from \"stream\";\nimport { storageDriverContext } from \"../context/storage-driver-context\";\nimport type {\n CloudStorageDriverContract,\n CloudStorageDriverOptions,\n CloudStorageFileData,\n DeleteManyResult,\n FileVisibility,\n ListOptions,\n PresignedOptions,\n PresignedUploadOptions,\n PutOptions,\n StorageDriverType,\n StorageFileInfo,\n} from \"../types\";\nimport { getMimeType } from \"../utils/mime\";\nimport { StorageCapabilityError } from \"../utils/storage-capability-error\";\n\n// ============================================================\n// Lazy-loaded S3 SDK Types\n// ============================================================\n\n/**\n * Cached S3 SDK modules (loaded once, reused)\n */\nlet S3Client: typeof import(\"@aws-sdk/client-s3\");\nlet S3Storage: typeof import(\"@aws-sdk/lib-storage\");\nlet S3Presigner: typeof import(\"@aws-sdk/s3-request-presigner\");\n\nlet isModuleExists: boolean | null = null;\n\n/**\n * Installation instructions for S3 SDK packages\n */\nconst S3_INSTALL_INSTRUCTIONS = `\nCloud storage requires the AWS S3 SDK packages.\nInstall them with:\n\n warlock add s3\n\n(raw packages: @aws-sdk/client-s3, @aws-sdk/lib-storage, @aws-sdk/s3-request-presigner)\n`.trim();\n\n/**\n * Atomic initialization promise to handle concurrent calls to loadS3\n */\nlet initializationPromise: Promise<void> | null = null;\n\n/**\n * Load S3 modules lazily\n *\n * @example\n * await loadS3();\n * if (isModuleExists) {\n * // Safe to use S3Client, S3Storage, S3Presigner\n * }\n */\nexport async function loadS3(): Promise<void> {\n // If already successfully loaded, no need to do anything\n if (isModuleExists === true) return;\n\n // If currently loading, return the existing promise so the caller waits\n if (initializationPromise) return initializationPromise;\n\n initializationPromise = (async () => {\n try {\n // Use Promise.all to load modules in parallel for efficiency\n const [client, storage, presigner] = await Promise.all([\n import(\"@aws-sdk/client-s3\"),\n import(\"@aws-sdk/lib-storage\"),\n import(\"@aws-sdk/s3-request-presigner\"),\n ]);\n\n S3Client = client;\n S3Storage = storage;\n S3Presigner = presigner;\n\n isModuleExists = true;\n } catch {\n // Mark as failed if any import fails (usually means packages aren't installed)\n isModuleExists = false;\n }\n })();\n\n return initializationPromise;\n}\n\nloadS3();\n\n/**\n * Synchronous fallback loader.\n *\n * `loadS3()` above is async and fire-and-forget at module load, so on the\n * very first *synchronous* `CloudDriver` construction the dynamic `import()`\n * microtask has not yet resolved — `isModuleExists` is still `null` even when\n * the SDK is genuinely installed. The constructor's install-check would then\n * throw the misleading \"SDK not installed\" error.\n *\n * This probes the modules synchronously via `require` (the AWS SDK ships\n * CJS-compatible builds) so a present SDK resolves the install-check\n * immediately, without waiting on the async path. Returns `true` when all\n * three modules loaded, `false` otherwise. Only invoked while\n * `isModuleExists` is still indeterminate.\n */\nfunction loadS3Sync(): boolean {\n if (isModuleExists !== null) {\n return isModuleExists;\n }\n\n try {\n // `createRequire` gives an ESM-safe synchronous `require` regardless of\n // whether this module runs as CJS or ESM at runtime.\n const req = createRequire(import.meta.url);\n S3Client = req(\"@aws-sdk/client-s3\");\n S3Storage = req(\"@aws-sdk/lib-storage\");\n S3Presigner = req(\"@aws-sdk/s3-request-presigner\");\n isModuleExists = true;\n } catch {\n isModuleExists = false;\n }\n\n return isModuleExists;\n}\n\n// ============================================================\n// CloudDriver Base Class\n// ============================================================\n\n/**\n * Base abstract class for all S3-compatible cloud storage drivers\n *\n * This class contains all shared logic for S3-compatible storage services\n * including AWS S3, Cloudflare R2, DigitalOcean Spaces, and others.\n *\n * **Important:** S3 SDK packages are lazy-loaded on first use.\n * Users must install them separately:\n * ```\n * npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner\n * ```\n *\n * Subclasses must implement:\n * - `name`: Driver identifier (e.g., \"s3\", \"r2\", \"spaces\")\n * - `url()`: Returns the public URL for a file (provider-specific format)\n */\nexport abstract class CloudDriver<\n TOptions extends Partial<CloudStorageDriverOptions> = CloudStorageDriverOptions,\n> implements CloudStorageDriverContract {\n /**\n * S3-compatible client (lazy-loaded)\n */\n protected client!: InstanceType<typeof import(\"@aws-sdk/client-s3\").S3Client>;\n\n /**\n * Retry configuration\n */\n protected retryConfig: {\n maxRetries: number;\n initialDelayMs: number;\n maxDelayMs: number;\n backoffMultiplier: number;\n };\n\n /**\n * How object visibility is applied: per-object ACLs (default), bucket\n * policy (no per-object ACL is sent), or unsupported (\"none\").\n * Buckets with ACLs disabled (S3 BucketOwnerEnforced, R2) need\n * \"policy\" or \"none\".\n */\n protected get visibilityMode(): \"acl\" | \"policy\" | \"none\" {\n return (this.options as { visibilityMode?: \"acl\" | \"policy\" | \"none\" }).visibilityMode ?? \"acl\";\n }\n\n /**\n * Resolve the ACL to send on a put for the requested visibility.\n *\n * @throws {StorageCapabilityError} When public is requested but the driver has no visibility support\n */\n protected resolveAcl(visibility?: FileVisibility): \"public-read\" | undefined {\n if (visibility !== \"public\") return undefined;\n\n if (this.visibilityMode === \"none\") {\n throw new StorageCapabilityError(\"public visibility\", this.name);\n }\n\n return this.visibilityMode === \"acl\" ? \"public-read\" : undefined;\n }\n\n public constructor(public options: TOptions) {\n // The async loadS3() may not have resolved yet on the first synchronous\n // construction. When the flag is still indeterminate, probe synchronously\n // so a genuinely-installed SDK never triggers the misleading throw below.\n if (isModuleExists === null) {\n loadS3Sync();\n }\n\n if (!isModuleExists) {\n throw new Error(S3_INSTALL_INSTRUCTIONS);\n }\n\n // Any remaining option is an S3ClientConfig option (forcePathStyle,\n // requestHandler, maxAttempts, ...) and is passed through to the SDK.\n const {\n bucket: _bucket,\n accessKeyId,\n secretAccessKey,\n endpoint: _endpoint,\n prefix: _prefix,\n urlPrefix: _urlPrefix,\n retry: _retry,\n accountId: _accountId,\n publicDomain: _publicDomain,\n driver: _driver,\n visibilityMode: _visibilityMode,\n ...clientOptions\n } = this.options as TOptions & Record<string, unknown>;\n\n this.client = new S3Client.S3Client({\n ...clientOptions,\n region: this.options.region!,\n // Without static keys the SDK default provider chain applies\n // (IAM role, ECS task role, IRSA, SSO profile).\n ...(accessKeyId && secretAccessKey && { credentials: { accessKeyId, secretAccessKey } }),\n ...(this.getEndpoint() && { endpoint: this.getEndpoint() }),\n } as import(\"@aws-sdk/client-s3\").S3ClientConfig);\n\n // Initialize retry configuration\n this.retryConfig = {\n maxRetries: this.options.retry?.maxRetries ?? 3,\n initialDelayMs: this.options.retry?.initialDelayMs ?? 1000,\n maxDelayMs: this.options.retry?.maxDelayMs ?? 10000,\n backoffMultiplier: this.options.retry?.backoffMultiplier ?? 2,\n };\n }\n\n /**\n * Driver name identifier\n */\n public abstract readonly name: StorageDriverType;\n\n /**\n * Get public URL for file\n * Must be implemented by subclasses with provider-specific format\n */\n public abstract url(location: string): string;\n\n /**\n * Get endpoint URL\n * Can be overridden by subclasses for provider-specific endpoints\n */\n protected getEndpoint(): string | undefined {\n return this.options.endpoint;\n }\n\n // ============================================================\n // Helper Methods\n // ============================================================\n\n /**\n * Apply prefix to location path\n *\n * Priority: context prefix > driver options prefix > no prefix\n * This allows multi-tenant scenarios where context overrides driver config.\n *\n * @param location - Original location path\n * @returns Location with prefix applied if one exists\n */\n public applyPrefix(location: string): string {\n // Check context prefix first (highest priority)\n const contextPrefix = storageDriverContext.getPrefix();\n const prefix = contextPrefix || this.options.prefix;\n\n if (!prefix) {\n return location;\n }\n\n const cleanPrefix = prefix.replace(/\\/+$/, \"\");\n const cleanLocation = location.replace(/^\\/+/, \"\");\n\n // Avoid double-prefixing\n if (cleanLocation.startsWith(cleanPrefix + \"/\") || cleanLocation === cleanPrefix) {\n return cleanLocation;\n }\n\n return `${cleanPrefix}/${cleanLocation}`;\n }\n\n /**\n * Normalize storage path (remove double slashes, sanitize)\n * @internal\n */\n protected normalizePath(path: string): string {\n return path\n .replace(/\\/+/g, \"/\") // Remove multiple slashes\n .replace(/^\\//, \"\") // Remove leading slash\n .trim();\n }\n\n /**\n * Execute an operation with retry logic\n *\n * Retries on transient errors with exponential backoff.\n *\n * @param operation - Async operation to execute\n * @param operationName - Name for logging\n * @returns Result of the operation\n * @internal\n */\n protected async withRetry<T>(\n operation: () => Promise<T>,\n operationName: string = \"operation\",\n ): Promise<T> {\n const { maxRetries, initialDelayMs, backoffMultiplier, maxDelayMs } = this.retryConfig;\n\n let lastError: unknown;\n\n // maxRetries counts retries, not attempts: 0 means a single attempt\n const attempts = maxRetries + 1;\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error;\n\n // Don't retry on the last attempt\n if (attempt === attempts - 1) {\n break;\n }\n\n // Check if error is retryable\n if (!this.isRetryableError(error)) {\n throw error; // Non-retryable error, fail immediately\n }\n\n // Calculate delay with exponential backoff\n const delayMs = Math.min(initialDelayMs * Math.pow(backoffMultiplier, attempt), maxDelayMs);\n\n // Wait before retrying\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n // Rethrow the original error so name/$metadata survive\n throw lastError;\n }\n\n /**\n * Check if an error is retryable\n *\n * Retries on:\n * - Network errors\n * - 5xx server errors\n * - Rate limiting (429)\n * - Timeout errors\n *\n * Does NOT retry on:\n * - 4xx client errors (except 429)\n * - Authentication errors\n * - Not found errors\n *\n * @param error - Error to check\n * @returns true if error is retryable\n * @internal\n */\n protected isRetryableError(error: any): boolean {\n // Network errors\n if (error.code === \"ECONNRESET\" || error.code === \"ETIMEDOUT\" || error.code === \"ENOTFOUND\") {\n return true;\n }\n\n // S3 SDK errors\n if (error.name === \"NetworkingError\" || error.name === \"TimeoutError\") {\n return true;\n }\n\n // HTTP status codes\n const statusCode = error.$metadata?.httpStatusCode || error.statusCode;\n if (statusCode) {\n // 5xx server errors are retryable\n if (statusCode >= 500 && statusCode < 600) {\n return true;\n }\n\n // 429 Too Many Requests is retryable\n if (statusCode === 429) {\n return true;\n }\n }\n\n return false;\n }\n\n // ============================================================\n // Core File Operations\n // ============================================================\n\n /**\n * Put file to cloud storage\n */\n public async put(\n file: Buffer,\n location: string,\n options?: PutOptions,\n ): Promise<CloudStorageFileData> {\n return this.withRetry(async () => {\n const { PutObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const hash = this.calculateHash(file);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n const command = new PutObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n Body: file,\n ContentType: mimeType,\n CacheControl: options?.cacheControl,\n ContentDisposition: options?.contentDisposition,\n Metadata: options?.metadata,\n ACL: this.resolveAcl(options?.visibility),\n });\n\n const result = await this.client.send(command);\n\n return {\n path: location,\n url: this.url(location),\n size: file.length,\n hash,\n mimeType,\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.ETag,\n versionId: result.VersionId,\n };\n }, \"put\");\n }\n\n /**\n * Atomically put a file only if the key does not exist (S3 conditional\n * write, `If-None-Match: *`).\n *\n * HTTP 412 (PreconditionFailed) and 409 (ConditionalRequestConflict, a\n * concurrent conditional write in flight) mean \"already exists\" and return\n * `null`. Every other error throws.\n */\n public async putIfAbsent(\n file: Buffer | string,\n location: string,\n options?: PutOptions,\n ): Promise<CloudStorageFileData | null> {\n const body = typeof file === \"string\" ? Buffer.from(file) : file;\n\n return this.withRetry(async () => {\n const { PutObjectCommand } = S3Client;\n\n location = this.applyPrefix(location);\n\n const hash = this.calculateHash(body);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n const command = new PutObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n Body: body,\n ContentType: mimeType,\n CacheControl: options?.cacheControl,\n ContentDisposition: options?.contentDisposition,\n Metadata: options?.metadata,\n ACL: this.resolveAcl(options?.visibility),\n IfNoneMatch: \"*\",\n });\n\n let result;\n\n try {\n result = await this.client.send(command);\n } catch (error: any) {\n const status = error?.$metadata?.httpStatusCode;\n\n if (\n status === 412 ||\n status === 409 ||\n error?.name === \"PreconditionFailed\" ||\n error?.name === \"ConditionalRequestConflict\"\n ) {\n return null;\n }\n\n throw error;\n }\n\n return {\n path: location,\n url: this.url(location),\n size: body.length,\n hash,\n mimeType,\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.ETag,\n versionId: result.VersionId,\n };\n }, \"putIfAbsent\");\n }\n\n /**\n * Put file from a readable stream (for large files)\n * Uses S3 multipart upload for efficient streaming\n */\n public async putStream(\n stream: Readable,\n location: string,\n options?: PutOptions,\n ): Promise<CloudStorageFileData> {\n // Not wrapped in withRetry: a retry would replay an already-consumed\n // stream, and lib-storage already retries individual parts.\n {\n const { Upload } = S3Storage;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n const upload = new Upload({\n client: this.client,\n params: {\n Bucket: this.options.bucket,\n Key: location,\n Body: stream,\n ContentType: mimeType,\n CacheControl: options?.cacheControl,\n ContentDisposition: options?.contentDisposition,\n Metadata: options?.metadata,\n ACL: this.resolveAcl(options?.visibility),\n },\n });\n\n const result = await upload.done();\n\n // Get file info for size and hash\n const info = await this.metadata(location);\n\n return {\n path: location,\n url: this.url(location),\n size: info.size,\n hash: info.etag?.replace(/\"/g, \"\") || \"\",\n mimeType,\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.ETag,\n versionId: result.VersionId,\n };\n }\n }\n\n /**\n * Get file contents as Buffer\n */\n public async get(location: string): Promise<Buffer> {\n return this.withRetry(async () => {\n const { GetObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n\n if (!result.Body) {\n throw new Error(`File not found: ${location}`);\n }\n\n return Buffer.from(await result.Body.transformToByteArray());\n }, \"get\");\n }\n\n /**\n * Get file as a readable stream (for large files)\n */\n public async getStream(location: string): Promise<Readable> {\n return this.withRetry(async () => {\n const { GetObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n\n if (!result.Body) {\n throw new Error(`File not found: ${location}`);\n }\n\n return result.Body as Readable;\n }, \"getStream\");\n }\n\n /**\n * Delete a file\n */\n public async delete(location: string): Promise<boolean> {\n return this.withRetry(async () => {\n const { DeleteObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new DeleteObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n await this.client.send(command);\n\n return true;\n }, \"delete\");\n }\n\n /**\n * Delete multiple files at once (uses batch delete for efficiency)\n */\n public async deleteMany(locations: string[]): Promise<DeleteManyResult[]> {\n if (locations.length === 0) {\n return [];\n }\n\n return this.withRetry(async () => {\n const { DeleteObjectsCommand } = S3Client;\n\n // Apply storage prefix to all locations\n const prefixedLocations = locations.map((loc) => this.applyPrefix(loc));\n\n const command = new DeleteObjectsCommand({\n Bucket: this.options.bucket,\n Delete: {\n Objects: prefixedLocations.map((Key) => ({ Key })),\n Quiet: false,\n },\n });\n\n const result = await this.client.send(command);\n const results: DeleteManyResult[] = [];\n\n // Process successful deletes\n for (const deleted of result.Deleted || []) {\n if (deleted.Key) {\n results.push({ location: deleted.Key, deleted: true });\n }\n }\n\n // Process errors\n for (const error of result.Errors || []) {\n if (error.Key) {\n results.push({\n location: error.Key,\n deleted: false,\n error: error.Message || \"Unknown error\",\n });\n }\n }\n\n return results;\n }, \"deleteMany\");\n }\n\n /**\n * Delete directory (recursively deletes all objects with matching prefix)\n *\n * S3/R2 doesn't have true directories - only key prefixes.\n * This method lists all objects with the prefix and deletes them in batches.\n *\n * @param directoryPath - Directory prefix to delete\n * @returns true when all objects are deleted\n */\n public async deleteDirectory(directoryPath: string): Promise<boolean> {\n const { ListObjectsV2Command, DeleteObjectsCommand } = S3Client;\n\n // Apply storage prefix\n directoryPath = this.applyPrefix(directoryPath);\n\n // Ensure directory path ends with / for proper prefix matching\n const prefix = directoryPath.endsWith(\"/\") ? directoryPath : `${directoryPath}/`;\n\n // Drive the loop with the ListObjectsV2 IsTruncated / ContinuationToken\n // contract rather than guessing termination from page size. Each page\n // carries its own ContinuationToken so we never re-list page one.\n let continuationToken: string | undefined;\n\n do {\n const listResult = await this.withRetry(\n () =>\n this.client.send(\n new ListObjectsV2Command({\n Bucket: this.options.bucket,\n Prefix: prefix,\n ContinuationToken: continuationToken,\n }),\n ),\n \"deleteDirectory:list\",\n );\n\n const keys = (listResult.Contents || [])\n .map((object) => object.Key)\n .filter((key): key is string => Boolean(key));\n\n if (keys.length > 0) {\n // Delete the raw keys directly — they already carry the full prefix\n // from the listing, so we bypass deleteMany's applyPrefix step.\n await this.withRetry(\n () =>\n this.client.send(\n new DeleteObjectsCommand({\n Bucket: this.options.bucket,\n Delete: {\n Objects: keys.map((Key) => ({ Key })),\n Quiet: true,\n },\n }),\n ),\n \"deleteDirectory:delete\",\n );\n }\n\n continuationToken = listResult.IsTruncated ? listResult.NextContinuationToken : undefined;\n } while (continuationToken);\n\n return true;\n }\n\n /**\n * Check if file exists\n */\n public async exists(location: string): Promise<boolean> {\n // No retry for exists - it should be fast and failure means non-existent\n try {\n const { HeadObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new HeadObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n await this.client.send(command);\n return true;\n } catch (error) {\n // Only a definite \"not found\" means absent; credential/network/5xx\n // errors must surface, otherwise `if (!exists) put()` overwrites.\n const { name, $metadata } = (error ?? {}) as {\n name?: string;\n $metadata?: { httpStatusCode?: number };\n };\n\n if (name === \"NotFound\" || name === \"NoSuchKey\" || $metadata?.httpStatusCode === 404) {\n return false;\n }\n\n throw error;\n }\n }\n\n // ============================================================\n // URL Operations\n // ============================================================\n\n /**\n * Get a temporary presigned URL (alias for getPresignedUrl)\n */\n public async temporaryUrl(location: string, expiresIn = 3600): Promise<string> {\n return this.getPresignedUrl(location, { expiresIn });\n }\n\n /**\n * Get presigned URL for downloading\n */\n public async getPresignedUrl(location: string, options?: PresignedOptions): Promise<string> {\n return this.withRetry(async () => {\n const { GetObjectCommand } = S3Client;\n const { getSignedUrl } = S3Presigner;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n return getSignedUrl(this.client, command, {\n expiresIn: options?.expiresIn || 3600,\n });\n }, \"getPresignedUrl\");\n }\n\n /**\n * Get presigned URL for uploading\n */\n public async getPresignedUploadUrl(\n location: string,\n options?: PresignedUploadOptions,\n ): Promise<string> {\n return this.withRetry(async () => {\n const { PutObjectCommand } = S3Client;\n const { getSignedUrl } = S3Presigner;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new PutObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n ContentType: options?.contentType,\n Metadata: options?.metadata,\n });\n\n return getSignedUrl(this.client, command, {\n expiresIn: options?.expiresIn || 3600,\n });\n }, \"getPresignedUploadUrl\");\n }\n\n // ============================================================\n // Metadata Operations\n // ============================================================\n\n /**\n * Get file info/metadata without downloading\n */\n public async metadata(location: string): Promise<StorageFileInfo> {\n return this.withRetry(async () => {\n const { HeadObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new HeadObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n const name = location.split(\"/\").pop() || \"\";\n\n return {\n path: location,\n name,\n size: result.ContentLength || 0,\n isDirectory: false,\n lastModified: result.LastModified,\n mimeType: result.ContentType || this.guessMimeType(location),\n etag: result.ETag,\n storageClass: result.StorageClass,\n };\n }, \"metadata\");\n }\n\n /**\n * Get file size in bytes (shortcut for metadata().size)\n */\n public async size(location: string): Promise<number> {\n const info = await this.metadata(location);\n return info.size;\n }\n\n // ============================================================\n // File Operations\n // ============================================================\n\n /**\n * Build a URL-encoded CopySource (\"bucket/key\") as the SDK requires\n */\n protected copySource(key: string): string {\n const encodedKey = key.split(\"/\").map(encodeURIComponent).join(\"/\");\n\n return `${this.options.bucket}/${encodedKey}`;\n }\n\n /**\n * Copy file to a new location\n */\n public async copy(from: string, to: string): Promise<CloudStorageFileData> {\n return this.withRetry(async () => {\n const { CopyObjectCommand, HeadObjectCommand } = S3Client;\n\n // CopyObject drops the ACL, so a public source would silently become private\n const visibility = await this.getVisibility(from).catch(() => \"private\" as const);\n\n // Apply storage prefix to both paths\n from = this.applyPrefix(from);\n to = this.applyPrefix(to);\n\n const command = new CopyObjectCommand({\n Bucket: this.options.bucket,\n CopySource: this.copySource(from),\n Key: to,\n ...(this.visibilityMode === \"acl\" && visibility === \"public\" && { ACL: \"public-read\" as const }),\n });\n\n const result = await this.client.send(command);\n\n // Get file metadata\n const headCommand = new HeadObjectCommand({\n Bucket: this.options.bucket,\n Key: to,\n });\n const headResult = await this.client.send(headCommand);\n\n return {\n path: to,\n url: this.url(to),\n size: headResult.ContentLength || 0,\n hash: headResult.ETag?.replace(/\"/g, \"\") || \"\",\n mimeType: headResult.ContentType || this.guessMimeType(to),\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.CopyObjectResult?.ETag,\n versionId: result.VersionId,\n };\n }, \"copy\");\n }\n\n /**\n * Move file to a new location\n */\n public async move(from: string, to: string): Promise<CloudStorageFileData> {\n const file = await this.copy(from, to);\n await this.delete(from);\n return file;\n }\n\n /**\n * List files in a directory\n */\n public async list(directory: string, options?: ListOptions): Promise<StorageFileInfo[]> {\n return this.withRetry(async () => {\n const { ListObjectsV2Command } = S3Client;\n\n // Apply storage prefix\n directory = this.applyPrefix(directory);\n\n // A directory prefix must end in \"/\" so \"images\" doesn't match \"images-old/…\"\n if (directory && directory !== \"/\" && !directory.endsWith(\"/\")) {\n directory = `${directory}/`;\n }\n\n const command = new ListObjectsV2Command({\n Bucket: this.options.bucket,\n Prefix: directory,\n MaxKeys: options?.limit,\n ContinuationToken: options?.cursor,\n Delimiter: options?.recursive ? undefined : \"/\",\n });\n\n const result = await this.client.send(command);\n const files: StorageFileInfo[] = [];\n\n // Add files\n for (const object of result.Contents || []) {\n if (!object.Key) continue;\n\n files.push({\n path: object.Key,\n name: object.Key.split(\"/\").pop() || \"\",\n size: object.Size || 0,\n isDirectory: false,\n lastModified: object.LastModified,\n etag: object.ETag,\n storageClass: object.StorageClass,\n });\n }\n\n // Add directories\n for (const prefix of result.CommonPrefixes || []) {\n if (!prefix.Prefix) continue;\n\n files.push({\n path: prefix.Prefix,\n name: prefix.Prefix.split(\"/\").filter(Boolean).pop() || \"\",\n size: 0,\n isDirectory: true,\n });\n }\n\n return files;\n }, \"list\");\n }\n\n // ============================================================\n // Cloud-Specific Operations\n // ============================================================\n\n /**\n * Get bucket name\n */\n public getBucket(): string {\n return this.options.bucket!;\n }\n\n /**\n * Get region\n */\n public getRegion(): string {\n return this.options.region!;\n }\n\n /**\n * Set storage class (e.g., STANDARD, GLACIER, etc.)\n */\n public async setStorageClass(location: string, storageClass: string): Promise<void> {\n return this.withRetry(async () => {\n const { CopyObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new CopyObjectCommand({\n Bucket: this.options.bucket,\n CopySource: this.copySource(location),\n Key: location,\n StorageClass: storageClass as any,\n MetadataDirective: \"COPY\",\n });\n\n await this.client.send(command);\n }, \"setStorageClass\");\n }\n\n /**\n * Set file visibility (public or private)\n */\n public async setVisibility(location: string, visibility: FileVisibility): Promise<void> {\n if (this.visibilityMode !== \"acl\") {\n throw new StorageCapabilityError(\"setVisibility\", this.name);\n }\n\n return this.withRetry(async () => {\n const { PutObjectAclCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new PutObjectAclCommand({\n Bucket: this.options.bucket,\n Key: location,\n ACL: visibility === \"public\" ? \"public-read\" : \"private\",\n });\n\n await this.client.send(command);\n }, \"setVisibility\");\n }\n\n /**\n * Get file visibility\n */\n public async getVisibility(location: string): Promise<FileVisibility> {\n return this.withRetry(async () => {\n const { GetObjectAclCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectAclCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n\n // Check if any grant allows public read\n const hasPublicRead = result.Grants?.some(\n (grant) =>\n grant.Grantee?.URI === \"http://acs.amazonaws.com/groups/global/AllUsers\" &&\n grant.Permission === \"READ\",\n );\n\n return hasPublicRead ? \"public\" : \"private\";\n }, \"getVisibility\");\n }\n\n // ============================================================\n // Utilities\n // ============================================================\n\n /**\n * Calculate SHA-256 hash\n */\n protected calculateHash(buffer: Buffer): string {\n return crypto.createHash(\"sha256\").update(new Uint8Array(buffer)).digest(\"hex\");\n }\n\n /**\n * Guess MIME type from file extension\n */\n protected guessMimeType(location: string): string {\n return getMimeType(location);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cloud-driver.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/cloud-driver.ts"],"sourcesContent":["import crypto from \"crypto\";\nimport { createRequire } from \"module\";\nimport type { Readable } from \"stream\";\nimport { storageDriverContext } from \"../context/storage-driver-context\";\nimport type {\n CloudStorageDriverContract,\n CloudStorageDriverOptions,\n CloudStorageFileData,\n DeleteManyResult,\n FileVisibility,\n ListOptions,\n PresignedOptions,\n PresignedUploadOptions,\n PutOptions,\n StorageDriverType,\n StorageFileInfo,\n} from \"../types\";\nimport { getMimeType } from \"../utils/mime\";\nimport { StorageCapabilityError } from \"../utils/storage-capability-error\";\n\n// ============================================================\n// Lazy-loaded S3 SDK Types\n// ============================================================\n\n/**\n * Cached S3 SDK modules (loaded once, reused)\n */\nlet S3Client: typeof import(\"@aws-sdk/client-s3\");\nlet S3Storage: typeof import(\"@aws-sdk/lib-storage\");\nlet S3Presigner: typeof import(\"@aws-sdk/s3-request-presigner\");\n\nlet isModuleExists: boolean | null = null;\n\n/**\n * Installation instructions for S3 SDK packages\n */\nconst S3_INSTALL_INSTRUCTIONS = `\nCloud storage requires the AWS S3 SDK packages.\nInstall them with:\n\n warlock add s3\n\n(raw packages: @aws-sdk/client-s3, @aws-sdk/lib-storage, @aws-sdk/s3-request-presigner)\n`.trim();\n\n/**\n * Atomic initialization promise to handle concurrent calls to loadS3\n */\nlet initializationPromise: Promise<void> | null = null;\n\n/**\n * Load S3 modules lazily\n *\n * @example\n * await loadS3();\n * if (isModuleExists) {\n * // Safe to use S3Client, S3Storage, S3Presigner\n * }\n */\nexport async function loadS3(): Promise<void> {\n // If already successfully loaded, no need to do anything\n if (isModuleExists === true) return;\n\n // If currently loading, return the existing promise so the caller waits\n if (initializationPromise) return initializationPromise;\n\n initializationPromise = (async () => {\n try {\n // Use Promise.all to load modules in parallel for efficiency\n const [client, storage, presigner] = await Promise.all([\n import(\"@aws-sdk/client-s3\"),\n import(\"@aws-sdk/lib-storage\"),\n import(\"@aws-sdk/s3-request-presigner\"),\n ]);\n\n S3Client = client;\n S3Storage = storage;\n S3Presigner = presigner;\n\n isModuleExists = true;\n } catch {\n // Mark as failed if any import fails (usually means packages aren't installed)\n isModuleExists = false;\n }\n })();\n\n return initializationPromise;\n}\n\nloadS3();\n\n/**\n * Synchronous fallback loader.\n *\n * `loadS3()` above is async and fire-and-forget at module load, so on the\n * very first *synchronous* `CloudDriver` construction the dynamic `import()`\n * microtask has not yet resolved — `isModuleExists` is still `null` even when\n * the SDK is genuinely installed. The constructor's install-check would then\n * throw the misleading \"SDK not installed\" error.\n *\n * This probes the modules synchronously via `require` (the AWS SDK ships\n * CJS-compatible builds) so a present SDK resolves the install-check\n * immediately, without waiting on the async path. Returns `true` when all\n * three modules loaded, `false` otherwise. Only invoked while\n * `isModuleExists` is still indeterminate.\n */\nfunction loadS3Sync(): boolean {\n if (isModuleExists !== null) {\n return isModuleExists;\n }\n\n try {\n // `createRequire` gives an ESM-safe synchronous `require` regardless of\n // whether this module runs as CJS or ESM at runtime.\n const req = createRequire(import.meta.url);\n S3Client = req(\"@aws-sdk/client-s3\");\n S3Storage = req(\"@aws-sdk/lib-storage\");\n S3Presigner = req(\"@aws-sdk/s3-request-presigner\");\n isModuleExists = true;\n } catch {\n isModuleExists = false;\n }\n\n return isModuleExists;\n}\n\n// ============================================================\n// CloudDriver Base Class\n// ============================================================\n\n/**\n * Base abstract class for all S3-compatible cloud storage drivers\n *\n * This class contains all shared logic for S3-compatible storage services\n * including AWS S3, Cloudflare R2, DigitalOcean Spaces, and others.\n *\n * **Important:** S3 SDK packages are lazy-loaded on first use.\n * Users must install them separately:\n * ```\n * npm install @aws-sdk/client-s3 @aws-sdk/lib-storage @aws-sdk/s3-request-presigner\n * ```\n *\n * Subclasses must implement:\n * - `name`: Driver identifier (e.g., \"s3\", \"r2\", \"spaces\")\n * - `url()`: Returns the public URL for a file (provider-specific format)\n */\nexport abstract class CloudDriver<\n TOptions extends Partial<CloudStorageDriverOptions> = CloudStorageDriverOptions,\n> implements CloudStorageDriverContract {\n /**\n * S3-compatible client (lazy-loaded)\n */\n protected client!: InstanceType<typeof import(\"@aws-sdk/client-s3\").S3Client>;\n\n /**\n * Retry configuration\n */\n protected retryConfig: {\n maxRetries: number;\n initialDelayMs: number;\n maxDelayMs: number;\n backoffMultiplier: number;\n };\n\n /**\n * How object visibility is applied: per-object ACLs (default), bucket\n * policy (no per-object ACL is sent), or unsupported (\"none\").\n * Buckets with ACLs disabled (S3 BucketOwnerEnforced, R2) need\n * \"policy\" or \"none\".\n */\n protected get visibilityMode(): \"acl\" | \"policy\" | \"none\" {\n return (this.options as { visibilityMode?: \"acl\" | \"policy\" | \"none\" }).visibilityMode ?? \"acl\";\n }\n\n /**\n * Resolve the ACL to send on a put for the requested visibility.\n *\n * @throws {StorageCapabilityError} When public is requested but the driver has no visibility support\n */\n protected resolveAcl(visibility?: FileVisibility): \"public-read\" | undefined {\n if (visibility !== \"public\") return undefined;\n\n if (this.visibilityMode === \"none\") {\n throw new StorageCapabilityError(\"public visibility\", this.name);\n }\n\n return this.visibilityMode === \"acl\" ? \"public-read\" : undefined;\n }\n\n public constructor(public options: TOptions) {\n // The async loadS3() may not have resolved yet on the first synchronous\n // construction. When the flag is still indeterminate, probe synchronously\n // so a genuinely-installed SDK never triggers the misleading throw below.\n if (isModuleExists === null) {\n loadS3Sync();\n }\n\n if (!isModuleExists) {\n throw new Error(S3_INSTALL_INSTRUCTIONS);\n }\n\n // Any remaining option is an S3ClientConfig option (forcePathStyle,\n // requestHandler, maxAttempts, ...) and is passed through to the SDK.\n const {\n bucket: _bucket,\n accessKeyId,\n secretAccessKey,\n endpoint: _endpoint,\n prefix: _prefix,\n urlPrefix: _urlPrefix,\n retry: _retry,\n accountId: _accountId,\n publicDomain: _publicDomain,\n driver: _driver,\n visibilityMode: _visibilityMode,\n ...clientOptions\n } = this.options as TOptions & Record<string, unknown>;\n\n this.client = new S3Client.S3Client({\n ...clientOptions,\n region: this.options.region!,\n // Without static keys the SDK default provider chain applies\n // (IAM role, ECS task role, IRSA, SSO profile).\n ...(accessKeyId && secretAccessKey && { credentials: { accessKeyId, secretAccessKey } }),\n ...(this.getEndpoint() && { endpoint: this.getEndpoint() }),\n } as import(\"@aws-sdk/client-s3\").S3ClientConfig);\n\n // Initialize retry configuration\n this.retryConfig = {\n maxRetries: this.options.retry?.maxRetries ?? 3,\n initialDelayMs: this.options.retry?.initialDelayMs ?? 1000,\n maxDelayMs: this.options.retry?.maxDelayMs ?? 10000,\n backoffMultiplier: this.options.retry?.backoffMultiplier ?? 2,\n };\n }\n\n /**\n * Driver name identifier\n */\n public abstract readonly name: StorageDriverType;\n\n /**\n * Get public URL for file\n * Must be implemented by subclasses with provider-specific format\n */\n public abstract url(location: string): string;\n\n /**\n * Get endpoint URL\n * Can be overridden by subclasses for provider-specific endpoints\n */\n protected getEndpoint(): string | undefined {\n return this.options.endpoint;\n }\n\n // ============================================================\n // Helper Methods\n // ============================================================\n\n /**\n * Apply prefix to location path\n *\n * Priority: context prefix > driver options prefix > no prefix\n * This allows multi-tenant scenarios where context overrides driver config.\n *\n * @param location - Original location path\n * @returns Location with prefix applied if one exists\n */\n public applyPrefix(location: string): string {\n // Check context prefix first (highest priority)\n const contextPrefix = storageDriverContext.getPrefix();\n const prefix = contextPrefix || this.options.prefix;\n\n if (!prefix) {\n return location;\n }\n\n const cleanPrefix = prefix.replace(/\\/+$/, \"\");\n const cleanLocation = location.replace(/^\\/+/, \"\");\n\n // Avoid double-prefixing\n if (cleanLocation.startsWith(cleanPrefix + \"/\") || cleanLocation === cleanPrefix) {\n return cleanLocation;\n }\n\n return `${cleanPrefix}/${cleanLocation}`;\n }\n\n /**\n * Normalize storage path (remove double slashes, sanitize)\n * @internal\n */\n protected normalizePath(path: string): string {\n return path\n .replace(/\\/+/g, \"/\") // Remove multiple slashes\n .replace(/^\\//, \"\") // Remove leading slash\n .trim();\n }\n\n /**\n * Execute an operation with retry logic\n *\n * Retries on transient errors with exponential backoff.\n *\n * @param operation - Async operation to execute\n * @param operationName - Name for logging\n * @returns Result of the operation\n * @internal\n */\n protected async withRetry<T>(\n operation: () => Promise<T>,\n operationName: string = \"operation\",\n ): Promise<T> {\n const { maxRetries, initialDelayMs, backoffMultiplier, maxDelayMs } = this.retryConfig;\n\n let lastError: unknown;\n\n // maxRetries counts retries, not attempts: 0 means a single attempt\n const attempts = maxRetries + 1;\n\n for (let attempt = 0; attempt < attempts; attempt++) {\n try {\n return await operation();\n } catch (error) {\n lastError = error;\n\n // Don't retry on the last attempt\n if (attempt === attempts - 1) {\n break;\n }\n\n // Check if error is retryable\n if (!this.isRetryableError(error)) {\n throw error; // Non-retryable error, fail immediately\n }\n\n // Calculate delay with exponential backoff\n const delayMs = Math.min(initialDelayMs * Math.pow(backoffMultiplier, attempt), maxDelayMs);\n\n // Wait before retrying\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n // Rethrow the original error so name/$metadata survive\n throw lastError;\n }\n\n /**\n * Check if an error is retryable\n *\n * Retries on:\n * - Network errors\n * - 5xx server errors\n * - Rate limiting (429)\n * - Timeout errors\n *\n * Does NOT retry on:\n * - 4xx client errors (except 429)\n * - Authentication errors\n * - Not found errors\n *\n * @param error - Error to check\n * @returns true if error is retryable\n * @internal\n */\n protected isRetryableError(error: any): boolean {\n // Network errors\n if (error.code === \"ECONNRESET\" || error.code === \"ETIMEDOUT\" || error.code === \"ENOTFOUND\") {\n return true;\n }\n\n // S3 SDK errors\n if (error.name === \"NetworkingError\" || error.name === \"TimeoutError\") {\n return true;\n }\n\n // HTTP status codes\n const statusCode = error.$metadata?.httpStatusCode || error.statusCode;\n if (statusCode) {\n // 5xx server errors are retryable\n if (statusCode >= 500 && statusCode < 600) {\n return true;\n }\n\n // 429 Too Many Requests is retryable\n if (statusCode === 429) {\n return true;\n }\n }\n\n return false;\n }\n\n // ============================================================\n // Core File Operations\n // ============================================================\n\n /**\n * Put file to cloud storage\n */\n public async put(\n file: Buffer,\n location: string,\n options?: PutOptions,\n ): Promise<CloudStorageFileData> {\n return this.withRetry(async () => {\n const { PutObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const hash = this.calculateHash(file);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n const command = new PutObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n Body: file,\n ContentType: mimeType,\n CacheControl: options?.cacheControl,\n ContentDisposition: options?.contentDisposition,\n Metadata: options?.metadata,\n ACL: this.resolveAcl(options?.visibility),\n });\n\n const result = await this.client.send(command);\n\n return {\n path: location,\n url: this.url(location),\n size: file.length,\n hash,\n mimeType,\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.ETag,\n versionId: result.VersionId,\n };\n }, \"put\");\n }\n\n /**\n * Atomically put a file only if the key does not exist (S3 conditional\n * write, `If-None-Match: *`).\n *\n * HTTP 412 (PreconditionFailed) and 409 (ConditionalRequestConflict, a\n * concurrent conditional write in flight) mean \"already exists\" and return\n * `null`. Every other error throws.\n */\n public async putIfAbsent(\n file: Buffer | string,\n location: string,\n options?: PutOptions,\n ): Promise<CloudStorageFileData | null> {\n const body = typeof file === \"string\" ? Buffer.from(file) : file;\n\n return this.withRetry(async () => {\n const { PutObjectCommand } = S3Client;\n\n location = this.applyPrefix(location);\n\n const hash = this.calculateHash(body);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n const command = new PutObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n Body: body,\n ContentType: mimeType,\n CacheControl: options?.cacheControl,\n ContentDisposition: options?.contentDisposition,\n Metadata: options?.metadata,\n ACL: this.resolveAcl(options?.visibility),\n IfNoneMatch: \"*\",\n });\n\n let result;\n\n try {\n result = await this.client.send(command);\n } catch (error: any) {\n const status = error?.$metadata?.httpStatusCode;\n\n if (\n status === 412 ||\n status === 409 ||\n error?.name === \"PreconditionFailed\" ||\n error?.name === \"ConditionalRequestConflict\"\n ) {\n return null;\n }\n\n throw error;\n }\n\n return {\n path: location,\n url: this.url(location),\n size: body.length,\n hash,\n mimeType,\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.ETag,\n versionId: result.VersionId,\n };\n }, \"putIfAbsent\");\n }\n\n /**\n * Put file from a readable stream (for large files)\n * Uses S3 multipart upload for efficient streaming\n */\n public async putStream(\n stream: Readable,\n location: string,\n options?: PutOptions,\n ): Promise<CloudStorageFileData> {\n // Not wrapped in withRetry: a retry would replay an already-consumed\n // stream, and lib-storage already retries individual parts.\n {\n const { Upload } = S3Storage;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n const upload = new Upload({\n client: this.client,\n params: {\n Bucket: this.options.bucket,\n Key: location,\n Body: stream,\n ContentType: mimeType,\n CacheControl: options?.cacheControl,\n ContentDisposition: options?.contentDisposition,\n Metadata: options?.metadata,\n ACL: this.resolveAcl(options?.visibility),\n },\n });\n\n const result = await upload.done();\n\n // Get file info for size and hash\n const info = await this.metadata(location);\n\n return {\n path: location,\n url: this.url(location),\n size: info.size,\n hash: info.etag?.replace(/\"/g, \"\") || \"\",\n mimeType,\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.ETag,\n versionId: result.VersionId,\n };\n }\n }\n\n /**\n * Get file contents as Buffer\n */\n public async get(location: string): Promise<Buffer> {\n return this.withRetry(async () => {\n const { GetObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n\n if (!result.Body) {\n throw new Error(`File not found: ${location}`);\n }\n\n return Buffer.from(await result.Body.transformToByteArray());\n }, \"get\");\n }\n\n /**\n * Get file as a readable stream (for large files)\n */\n public async getStream(location: string): Promise<Readable> {\n return this.withRetry(async () => {\n const { GetObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n\n if (!result.Body) {\n throw new Error(`File not found: ${location}`);\n }\n\n return result.Body as Readable;\n }, \"getStream\");\n }\n\n /**\n * Delete a file\n */\n public async delete(location: string): Promise<boolean> {\n return this.withRetry(async () => {\n const { DeleteObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new DeleteObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n await this.client.send(command);\n\n return true;\n }, \"delete\");\n }\n\n /**\n * Delete multiple files at once (uses batch delete for efficiency)\n */\n public async deleteMany(locations: string[]): Promise<DeleteManyResult[]> {\n if (locations.length === 0) {\n return [];\n }\n\n return this.withRetry(async () => {\n const { DeleteObjectsCommand } = S3Client;\n\n // Apply storage prefix to all locations\n const prefixedLocations = locations.map((loc) => this.applyPrefix(loc));\n\n const command = new DeleteObjectsCommand({\n Bucket: this.options.bucket,\n Delete: {\n Objects: prefixedLocations.map((Key) => ({ Key })),\n Quiet: false,\n },\n });\n\n const result = await this.client.send(command);\n const results: DeleteManyResult[] = [];\n\n // Process successful deletes\n for (const deleted of result.Deleted || []) {\n if (deleted.Key) {\n results.push({ location: deleted.Key, deleted: true });\n }\n }\n\n // Process errors\n for (const error of result.Errors || []) {\n if (error.Key) {\n results.push({\n location: error.Key,\n deleted: false,\n error: error.Message || \"Unknown error\",\n });\n }\n }\n\n return results;\n }, \"deleteMany\");\n }\n\n /**\n * Delete directory (recursively deletes all objects with matching prefix)\n *\n * S3/R2 doesn't have true directories - only key prefixes.\n * This method lists all objects with the prefix and deletes them in batches.\n *\n * @param directoryPath - Directory prefix to delete\n * @returns true when all objects are deleted\n */\n public async deleteDirectory(directoryPath: string): Promise<boolean> {\n const { ListObjectsV2Command, DeleteObjectsCommand } = S3Client;\n\n // Apply storage prefix\n directoryPath = this.applyPrefix(directoryPath);\n\n // Ensure directory path ends with / for proper prefix matching\n const prefix = directoryPath.endsWith(\"/\") ? directoryPath : `${directoryPath}/`;\n\n // Drive the loop with the ListObjectsV2 IsTruncated / ContinuationToken\n // contract rather than guessing termination from page size. Each page\n // carries its own ContinuationToken so we never re-list page one.\n let continuationToken: string | undefined;\n\n do {\n const listResult = await this.withRetry(\n () =>\n this.client.send(\n new ListObjectsV2Command({\n Bucket: this.options.bucket,\n Prefix: prefix,\n ContinuationToken: continuationToken,\n }),\n ),\n \"deleteDirectory:list\",\n );\n\n const keys = (listResult.Contents || [])\n .map((object) => object.Key)\n .filter((key): key is string => Boolean(key));\n\n if (keys.length > 0) {\n // Delete the raw keys directly — they already carry the full prefix\n // from the listing, so we bypass deleteMany's applyPrefix step.\n await this.withRetry(\n () =>\n this.client.send(\n new DeleteObjectsCommand({\n Bucket: this.options.bucket,\n Delete: {\n Objects: keys.map((Key) => ({ Key })),\n Quiet: true,\n },\n }),\n ),\n \"deleteDirectory:delete\",\n );\n }\n\n continuationToken = listResult.IsTruncated ? listResult.NextContinuationToken : undefined;\n } while (continuationToken);\n\n return true;\n }\n\n /**\n * Check if file exists\n */\n public async exists(location: string): Promise<boolean> {\n // No retry for exists - it should be fast and failure means non-existent\n try {\n const { HeadObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new HeadObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n await this.client.send(command);\n return true;\n } catch (error) {\n // Only a definite \"not found\" means absent; credential/network/5xx\n // errors must surface, otherwise `if (!exists) put()` overwrites.\n const { name, $metadata } = (error ?? {}) as {\n name?: string;\n $metadata?: { httpStatusCode?: number };\n };\n\n if (name === \"NotFound\" || name === \"NoSuchKey\" || $metadata?.httpStatusCode === 404) {\n return false;\n }\n\n throw error;\n }\n }\n\n // ============================================================\n // URL Operations\n // ============================================================\n\n /**\n * Get a temporary presigned URL (alias for getPresignedUrl)\n */\n public async temporaryUrl(location: string, expiresIn = 3600): Promise<string> {\n return this.getPresignedUrl(location, { expiresIn });\n }\n\n /**\n * Get presigned URL for downloading\n */\n public async getPresignedUrl(location: string, options?: PresignedOptions): Promise<string> {\n return this.withRetry(async () => {\n const { GetObjectCommand } = S3Client;\n const { getSignedUrl } = S3Presigner;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n return getSignedUrl(this.client, command, {\n expiresIn: options?.expiresIn || 3600,\n });\n }, \"getPresignedUrl\");\n }\n\n /**\n * Get presigned URL for uploading\n */\n public async getPresignedUploadUrl(\n location: string,\n options?: PresignedUploadOptions,\n ): Promise<string> {\n return this.withRetry(async () => {\n const { PutObjectCommand } = S3Client;\n const { getSignedUrl } = S3Presigner;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new PutObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n ContentType: options?.contentType,\n Metadata: options?.metadata,\n });\n\n return getSignedUrl(this.client, command, {\n expiresIn: options?.expiresIn || 3600,\n });\n }, \"getPresignedUploadUrl\");\n }\n\n // ============================================================\n // Metadata Operations\n // ============================================================\n\n /**\n * Get file info/metadata without downloading\n */\n public async metadata(location: string): Promise<StorageFileInfo> {\n return this.withRetry(async () => {\n const { HeadObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new HeadObjectCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n const name = location.split(\"/\").pop() || \"\";\n\n return {\n path: location,\n name,\n size: result.ContentLength || 0,\n isDirectory: false,\n lastModified: result.LastModified,\n mimeType: result.ContentType || this.guessMimeType(location),\n etag: result.ETag,\n storageClass: result.StorageClass,\n };\n }, \"metadata\");\n }\n\n /**\n * Get file size in bytes (shortcut for metadata().size)\n */\n public async size(location: string): Promise<number> {\n const info = await this.metadata(location);\n return info.size;\n }\n\n // ============================================================\n // File Operations\n // ============================================================\n\n /**\n * Build a URL-encoded CopySource (\"bucket/key\") as the SDK requires\n */\n protected copySource(key: string): string {\n const encodedKey = key.split(\"/\").map(encodeURIComponent).join(\"/\");\n\n return `${this.options.bucket}/${encodedKey}`;\n }\n\n /**\n * Copy file to a new location\n */\n public async copy(from: string, to: string): Promise<CloudStorageFileData> {\n return this.withRetry(async () => {\n const { CopyObjectCommand, HeadObjectCommand } = S3Client;\n\n // CopyObject drops the ACL, so a public source would silently become private\n const visibility = await this.getVisibility(from).catch(() => \"private\" as const);\n\n // Apply storage prefix to both paths\n from = this.applyPrefix(from);\n to = this.applyPrefix(to);\n\n const command = new CopyObjectCommand({\n Bucket: this.options.bucket,\n CopySource: this.copySource(from),\n Key: to,\n ...(this.visibilityMode === \"acl\" && visibility === \"public\" && { ACL: \"public-read\" as const }),\n });\n\n const result = await this.client.send(command);\n\n // Get file metadata\n const headCommand = new HeadObjectCommand({\n Bucket: this.options.bucket,\n Key: to,\n });\n const headResult = await this.client.send(headCommand);\n\n return {\n path: to,\n url: this.url(to),\n size: headResult.ContentLength || 0,\n hash: headResult.ETag?.replace(/\"/g, \"\") || \"\",\n mimeType: headResult.ContentType || this.guessMimeType(to),\n driver: this.name,\n bucket: this.options.bucket!,\n region: this.options.region!,\n etag: result.CopyObjectResult?.ETag,\n versionId: result.VersionId,\n };\n }, \"copy\");\n }\n\n /**\n * Move file to a new location\n */\n public async move(from: string, to: string): Promise<CloudStorageFileData> {\n const file = await this.copy(from, to);\n await this.delete(from);\n return file;\n }\n\n /**\n * List files in a directory\n */\n public async list(directory: string, options?: ListOptions): Promise<StorageFileInfo[]> {\n return this.withRetry(async () => {\n const { ListObjectsV2Command } = S3Client;\n\n // Apply storage prefix\n directory = this.applyPrefix(directory);\n\n // A directory prefix must end in \"/\" so \"images\" doesn't match \"images-old/…\"\n if (directory && directory !== \"/\" && !directory.endsWith(\"/\")) {\n directory = `${directory}/`;\n }\n\n const command = new ListObjectsV2Command({\n Bucket: this.options.bucket,\n Prefix: directory,\n MaxKeys: options?.limit,\n ContinuationToken: options?.cursor,\n Delimiter: options?.recursive ? undefined : \"/\",\n });\n\n const result = await this.client.send(command);\n const files: StorageFileInfo[] = [];\n\n // Add files\n for (const object of result.Contents || []) {\n if (!object.Key) continue;\n\n files.push({\n path: object.Key,\n name: object.Key.split(\"/\").pop() || \"\",\n size: object.Size || 0,\n isDirectory: false,\n lastModified: object.LastModified,\n etag: object.ETag,\n storageClass: object.StorageClass,\n });\n }\n\n // Add directories\n for (const prefix of result.CommonPrefixes || []) {\n if (!prefix.Prefix) continue;\n\n files.push({\n path: prefix.Prefix,\n name: prefix.Prefix.split(\"/\").filter(Boolean).pop() || \"\",\n size: 0,\n isDirectory: true,\n });\n }\n\n return files;\n }, \"list\");\n }\n\n // ============================================================\n // Cloud-Specific Operations\n // ============================================================\n\n /**\n * Get bucket name\n */\n public getBucket(): string {\n return this.options.bucket!;\n }\n\n /**\n * Get region\n */\n public getRegion(): string {\n return this.options.region!;\n }\n\n /**\n * Set storage class (e.g., STANDARD, GLACIER, etc.)\n */\n public async setStorageClass(location: string, storageClass: string): Promise<void> {\n return this.withRetry(async () => {\n const { CopyObjectCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new CopyObjectCommand({\n Bucket: this.options.bucket,\n CopySource: this.copySource(location),\n Key: location,\n StorageClass: storageClass as any,\n MetadataDirective: \"COPY\",\n });\n\n await this.client.send(command);\n }, \"setStorageClass\");\n }\n\n /**\n * Set file visibility (public or private)\n */\n public async setVisibility(location: string, visibility: FileVisibility): Promise<void> {\n if (this.visibilityMode !== \"acl\") {\n throw new StorageCapabilityError(\"setVisibility\", this.name);\n }\n\n return this.withRetry(async () => {\n const { PutObjectAclCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new PutObjectAclCommand({\n Bucket: this.options.bucket,\n Key: location,\n ACL: visibility === \"public\" ? \"public-read\" : \"private\",\n });\n\n await this.client.send(command);\n }, \"setVisibility\");\n }\n\n /**\n * Get file visibility\n */\n public async getVisibility(location: string): Promise<FileVisibility> {\n return this.withRetry(async () => {\n const { GetObjectAclCommand } = S3Client;\n\n // Apply storage prefix\n location = this.applyPrefix(location);\n\n const command = new GetObjectAclCommand({\n Bucket: this.options.bucket,\n Key: location,\n });\n\n const result = await this.client.send(command);\n\n // Check if any grant allows public read\n const hasPublicRead = result.Grants?.some(\n (grant) =>\n grant.Grantee?.URI === \"http://acs.amazonaws.com/groups/global/AllUsers\" &&\n grant.Permission === \"READ\",\n );\n\n return hasPublicRead ? \"public\" : \"private\";\n }, \"getVisibility\");\n }\n\n // ============================================================\n // Utilities\n // ============================================================\n\n /**\n * Calculate SHA-256 hash\n */\n protected calculateHash(buffer: Buffer): string {\n return crypto.createHash(\"sha256\").update(new Uint8Array(buffer)).digest(\"hex\");\n }\n\n /**\n * Guess MIME type from file extension\n */\n protected guessMimeType(location: string): string {\n return getMimeType(location);\n }\n}\n"],"mappings":";;;;;;;;;;AA2BA,IAAI;AACJ,IAAI;AACJ,IAAI;AAEJ,IAAI,iBAAiC;;;;AAKrC,MAAM,0BAA0B;;;;;;;EAO9B,KAAK;;;;AAKP,IAAI,wBAA8C;;;;;;;;;;AAWlD,eAAsB,SAAwB;CAE5C,IAAI,mBAAmB,MAAM;CAG7B,IAAI,uBAAuB,OAAO;CAElC,yBAAyB,YAAY;EACnC,IAAI;GAEF,MAAM,CAAC,QAAQ,SAAS,aAAa,MAAM,QAAQ,IAAI;IACrD,OAAO;IACP,OAAO;IACP,OAAO;GACT,CAAC;GAED,WAAW;GACX,YAAY;GACZ,cAAc;GAEd,iBAAiB;EACnB,QAAQ;GAEN,iBAAiB;EACnB;CACF,EAAC,CAAE;CAEH,OAAO;AACT;AAEA,OAAO;;;;;;;;;;;;;;;;AAiBP,SAAS,aAAsB;CAC7B,IAAI,mBAAmB,MACrB,OAAO;CAGT,IAAI;EAGF,MAAM,MAAM,cAAc,OAAO,KAAK,GAAG;EACzC,WAAW,IAAI,oBAAoB;EACnC,YAAY,IAAI,sBAAsB;EACtC,cAAc,IAAI,+BAA+B;EACjD,iBAAiB;CACnB,QAAQ;EACN,iBAAiB;CACnB;CAEA,OAAO;AACT;;;;;;;;;;;;;;;;;AAsBA,IAAsB,cAAtB,MAEwC;;;;;;;CAsBtC,IAAc,iBAA4C;EACxD,OAAQ,KAAK,QAA2D,kBAAkB;CAC5F;;;;;;CAOA,AAAU,WAAW,YAAwD;EAC3E,IAAI,eAAe,UAAU,OAAO;EAEpC,IAAI,KAAK,mBAAmB,QAC1B,MAAM,IAAI,uBAAuB,qBAAqB,KAAK,IAAI;EAGjE,OAAO,KAAK,mBAAmB,QAAQ,gBAAgB;CACzD;CAEA,AAAO,YAAY,AAAO,SAAmB;EAAnB;EAIxB,IAAI,mBAAmB,MACrB,WAAW;EAGb,IAAI,CAAC,gBACH,MAAM,IAAI,MAAM,uBAAuB;EAKzC,MAAM,EACJ,QAAQ,SACR,aACA,iBACA,UAAU,WACV,QAAQ,SACR,WAAW,YACX,OAAO,QACP,WAAW,YACX,cAAc,eACd,QAAQ,SACR,gBAAgB,iBAChB,GAAG,kBACD,KAAK;EAET,KAAK,SAAS,IAAI,SAAS,SAAS;GAClC,GAAG;GACH,QAAQ,KAAK,QAAQ;GAGrB,GAAI,eAAe,mBAAmB,EAAE,aAAa;IAAE;IAAa;GAAgB,EAAE;GACtF,GAAI,KAAK,YAAY,KAAK,EAAE,UAAU,KAAK,YAAY,EAAE;EAC3D,CAAgD;EAGhD,KAAK,cAAc;GACjB,YAAY,KAAK,QAAQ,OAAO,cAAc;GAC9C,gBAAgB,KAAK,QAAQ,OAAO,kBAAkB;GACtD,YAAY,KAAK,QAAQ,OAAO,cAAc;GAC9C,mBAAmB,KAAK,QAAQ,OAAO,qBAAqB;EAC9D;CACF;;;;;CAiBA,AAAU,cAAkC;EAC1C,OAAO,KAAK,QAAQ;CACtB;;;;;;;;;;CAeA,AAAO,YAAY,UAA0B;EAG3C,MAAM,SADgB,qBAAqB,UAChB,KAAK,KAAK,QAAQ;EAE7C,IAAI,CAAC,QACH,OAAO;EAGT,MAAM,cAAc,OAAO,QAAQ,QAAQ,EAAE;EAC7C,MAAM,gBAAgB,SAAS,QAAQ,QAAQ,EAAE;EAGjD,IAAI,cAAc,WAAW,cAAc,GAAG,KAAK,kBAAkB,aACnE,OAAO;EAGT,OAAO,GAAG,YAAY,GAAG;CAC3B;;;;;CAMA,AAAU,cAAc,MAAsB;EAC5C,OAAO,KACJ,QAAQ,QAAQ,GAAG,CAAC,CACpB,QAAQ,OAAO,EAAE,CAAC,CAClB,KAAK;CACV;;;;;;;;;;;CAYA,MAAgB,UACd,WACA,gBAAwB,aACZ;EACZ,MAAM,EAAE,YAAY,gBAAgB,mBAAmB,eAAe,KAAK;EAE3E,IAAI;EAGJ,MAAM,WAAW,aAAa;EAE9B,KAAK,IAAI,UAAU,GAAG,UAAU,UAAU,WACxC,IAAI;GACF,OAAO,MAAM,UAAU;EACzB,SAAS,OAAO;GACd,YAAY;GAGZ,IAAI,YAAY,WAAW,GACzB;GAIF,IAAI,CAAC,KAAK,iBAAiB,KAAK,GAC9B,MAAM;GAIR,MAAM,UAAU,KAAK,IAAI,iBAAiB,KAAK,IAAI,mBAAmB,OAAO,GAAG,UAAU;GAG1F,MAAM,IAAI,SAAS,YAAY,WAAW,SAAS,OAAO,CAAC;EAC7D;EAIF,MAAM;CACR;;;;;;;;;;;;;;;;;;;CAoBA,AAAU,iBAAiB,OAAqB;EAE9C,IAAI,MAAM,SAAS,gBAAgB,MAAM,SAAS,eAAe,MAAM,SAAS,aAC9E,OAAO;EAIT,IAAI,MAAM,SAAS,qBAAqB,MAAM,SAAS,gBACrD,OAAO;EAIT,MAAM,aAAa,MAAM,WAAW,kBAAkB,MAAM;EAC5D,IAAI,YAAY;GAEd,IAAI,cAAc,OAAO,aAAa,KACpC,OAAO;GAIT,IAAI,eAAe,KACjB,OAAO;EAEX;EAEA,OAAO;CACT;;;;CASA,MAAa,IACX,MACA,UACA,SAC+B;EAC/B,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,qBAAqB;GAG7B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,OAAO,KAAK,cAAc,IAAI;GACpC,MAAM,WAAW,SAAS,YAAY,KAAK,cAAc,QAAQ;GAEjE,MAAM,UAAU,IAAI,iBAAiB;IACnC,QAAQ,KAAK,QAAQ;IACrB,KAAK;IACL,MAAM;IACN,aAAa;IACb,cAAc,SAAS;IACvB,oBAAoB,SAAS;IAC7B,UAAU,SAAS;IACnB,KAAK,KAAK,WAAW,SAAS,UAAU;GAC1C,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAE7C,OAAO;IACL,MAAM;IACN,KAAK,KAAK,IAAI,QAAQ;IACtB,MAAM,KAAK;IACX;IACA;IACA,QAAQ,KAAK;IACb,QAAQ,KAAK,QAAQ;IACrB,QAAQ,KAAK,QAAQ;IACrB,MAAM,OAAO;IACb,WAAW,OAAO;GACpB;EACF,GAAG,KAAK;CACV;;;;;;;;;CAUA,MAAa,YACX,MACA,UACA,SACsC;EACtC,MAAM,OAAO,OAAO,SAAS,WAAW,OAAO,KAAK,IAAI,IAAI;EAE5D,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,qBAAqB;GAE7B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,OAAO,KAAK,cAAc,IAAI;GACpC,MAAM,WAAW,SAAS,YAAY,KAAK,cAAc,QAAQ;GAEjE,MAAM,UAAU,IAAI,iBAAiB;IACnC,QAAQ,KAAK,QAAQ;IACrB,KAAK;IACL,MAAM;IACN,aAAa;IACb,cAAc,SAAS;IACvB,oBAAoB,SAAS;IAC7B,UAAU,SAAS;IACnB,KAAK,KAAK,WAAW,SAAS,UAAU;IACxC,aAAa;GACf,CAAC;GAED,IAAI;GAEJ,IAAI;IACF,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GACzC,SAAS,OAAY;IACnB,MAAM,SAAS,OAAO,WAAW;IAEjC,IACE,WAAW,OACX,WAAW,OACX,OAAO,SAAS,wBAChB,OAAO,SAAS,8BAEhB,OAAO;IAGT,MAAM;GACR;GAEA,OAAO;IACL,MAAM;IACN,KAAK,KAAK,IAAI,QAAQ;IACtB,MAAM,KAAK;IACX;IACA;IACA,QAAQ,KAAK;IACb,QAAQ,KAAK,QAAQ;IACrB,QAAQ,KAAK,QAAQ;IACrB,MAAM,OAAO;IACb,WAAW,OAAO;GACpB;EACF,GAAG,aAAa;CAClB;;;;;CAMA,MAAa,UACX,QACA,UACA,SAC+B;EAG/B;GACE,MAAM,EAAE,WAAW;GAGnB,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,WAAW,SAAS,YAAY,KAAK,cAAc,QAAQ;GAgBjE,MAAM,SAAS,MAAM,IAdF,OAAO;IACxB,QAAQ,KAAK;IACb,QAAQ;KACN,QAAQ,KAAK,QAAQ;KACrB,KAAK;KACL,MAAM;KACN,aAAa;KACb,cAAc,SAAS;KACvB,oBAAoB,SAAS;KAC7B,UAAU,SAAS;KACnB,KAAK,KAAK,WAAW,SAAS,UAAU;IAC1C;GACF,CAE0B,CAAC,CAAC,KAAK;GAGjC,MAAM,OAAO,MAAM,KAAK,SAAS,QAAQ;GAEzC,OAAO;IACL,MAAM;IACN,KAAK,KAAK,IAAI,QAAQ;IACtB,MAAM,KAAK;IACX,MAAM,KAAK,MAAM,QAAQ,MAAM,EAAE,KAAK;IACtC;IACA,QAAQ,KAAK;IACb,QAAQ,KAAK,QAAQ;IACrB,QAAQ,KAAK,QAAQ;IACrB,MAAM,OAAO;IACb,WAAW,OAAO;GACpB;EACF;CACF;;;;CAKA,MAAa,IAAI,UAAmC;EAClD,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,qBAAqB;GAG7B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,iBAAiB;IACnC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAE7C,IAAI,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,mBAAmB,UAAU;GAG/C,OAAO,OAAO,KAAK,MAAM,OAAO,KAAK,qBAAqB,CAAC;EAC7D,GAAG,KAAK;CACV;;;;CAKA,MAAa,UAAU,UAAqC;EAC1D,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,qBAAqB;GAG7B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,iBAAiB;IACnC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAE7C,IAAI,CAAC,OAAO,MACV,MAAM,IAAI,MAAM,mBAAmB,UAAU;GAG/C,OAAO,OAAO;EAChB,GAAG,WAAW;CAChB;;;;CAKA,MAAa,OAAO,UAAoC;EACtD,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,wBAAwB;GAGhC,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,oBAAoB;IACtC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAED,MAAM,KAAK,OAAO,KAAK,OAAO;GAE9B,OAAO;EACT,GAAG,QAAQ;CACb;;;;CAKA,MAAa,WAAW,WAAkD;EACxE,IAAI,UAAU,WAAW,GACvB,OAAO,CAAC;EAGV,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,yBAAyB;GAGjC,MAAM,oBAAoB,UAAU,KAAK,QAAQ,KAAK,YAAY,GAAG,CAAC;GAEtE,MAAM,UAAU,IAAI,qBAAqB;IACvC,QAAQ,KAAK,QAAQ;IACrB,QAAQ;KACN,SAAS,kBAAkB,KAAK,SAAS,EAAE,IAAI,EAAE;KACjD,OAAO;IACT;GACF,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAC7C,MAAM,UAA8B,CAAC;GAGrC,KAAK,MAAM,WAAW,OAAO,WAAW,CAAC,GACvC,IAAI,QAAQ,KACV,QAAQ,KAAK;IAAE,UAAU,QAAQ;IAAK,SAAS;GAAK,CAAC;GAKzD,KAAK,MAAM,SAAS,OAAO,UAAU,CAAC,GACpC,IAAI,MAAM,KACR,QAAQ,KAAK;IACX,UAAU,MAAM;IAChB,SAAS;IACT,OAAO,MAAM,WAAW;GAC1B,CAAC;GAIL,OAAO;EACT,GAAG,YAAY;CACjB;;;;;;;;;;CAWA,MAAa,gBAAgB,eAAyC;EACpE,MAAM,EAAE,sBAAsB,yBAAyB;EAGvD,gBAAgB,KAAK,YAAY,aAAa;EAG9C,MAAM,SAAS,cAAc,SAAS,GAAG,IAAI,gBAAgB,GAAG,cAAc;EAK9E,IAAI;EAEJ,GAAG;GACD,MAAM,aAAa,MAAM,KAAK,gBAE1B,KAAK,OAAO,KACV,IAAI,qBAAqB;IACvB,QAAQ,KAAK,QAAQ;IACrB,QAAQ;IACR,mBAAmB;GACrB,CAAC,CACH,GACF,sBACF;GAEA,MAAM,QAAQ,WAAW,YAAY,CAAC,EAAC,CACpC,KAAK,WAAW,OAAO,GAAG,CAAC,CAC3B,QAAQ,QAAuB,QAAQ,GAAG,CAAC;GAE9C,IAAI,KAAK,SAAS,GAGhB,MAAM,KAAK,gBAEP,KAAK,OAAO,KACV,IAAI,qBAAqB;IACvB,QAAQ,KAAK,QAAQ;IACrB,QAAQ;KACN,SAAS,KAAK,KAAK,SAAS,EAAE,IAAI,EAAE;KACpC,OAAO;IACT;GACF,CAAC,CACH,GACF,wBACF;GAGF,oBAAoB,WAAW,cAAc,WAAW,wBAAwB;EAClF,SAAS;EAET,OAAO;CACT;;;;CAKA,MAAa,OAAO,UAAoC;EAEtD,IAAI;GACF,MAAM,EAAE,sBAAsB;GAG9B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,kBAAkB;IACpC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAED,MAAM,KAAK,OAAO,KAAK,OAAO;GAC9B,OAAO;EACT,SAAS,OAAO;GAGd,MAAM,EAAE,MAAM,cAAe,SAAS,CAAC;GAKvC,IAAI,SAAS,cAAc,SAAS,eAAe,WAAW,mBAAmB,KAC/E,OAAO;GAGT,MAAM;EACR;CACF;;;;CASA,MAAa,aAAa,UAAkB,YAAY,MAAuB;EAC7E,OAAO,KAAK,gBAAgB,UAAU,EAAE,UAAU,CAAC;CACrD;;;;CAKA,MAAa,gBAAgB,UAAkB,SAA6C;EAC1F,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,qBAAqB;GAC7B,MAAM,EAAE,iBAAiB;GAGzB,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,iBAAiB;IACnC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAED,OAAO,aAAa,KAAK,QAAQ,SAAS,EACxC,WAAW,SAAS,aAAa,KACnC,CAAC;EACH,GAAG,iBAAiB;CACtB;;;;CAKA,MAAa,sBACX,UACA,SACiB;EACjB,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,qBAAqB;GAC7B,MAAM,EAAE,iBAAiB;GAGzB,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,iBAAiB;IACnC,QAAQ,KAAK,QAAQ;IACrB,KAAK;IACL,aAAa,SAAS;IACtB,UAAU,SAAS;GACrB,CAAC;GAED,OAAO,aAAa,KAAK,QAAQ,SAAS,EACxC,WAAW,SAAS,aAAa,KACnC,CAAC;EACH,GAAG,uBAAuB;CAC5B;;;;CASA,MAAa,SAAS,UAA4C;EAChE,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,sBAAsB;GAG9B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,kBAAkB;IACpC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAC7C,MAAM,OAAO,SAAS,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;GAE1C,OAAO;IACL,MAAM;IACN;IACA,MAAM,OAAO,iBAAiB;IAC9B,aAAa;IACb,cAAc,OAAO;IACrB,UAAU,OAAO,eAAe,KAAK,cAAc,QAAQ;IAC3D,MAAM,OAAO;IACb,cAAc,OAAO;GACvB;EACF,GAAG,UAAU;CACf;;;;CAKA,MAAa,KAAK,UAAmC;EAEnD,QAAO,MADY,KAAK,SAAS,QAAQ,EAC9B,CAAC;CACd;;;;CASA,AAAU,WAAW,KAAqB;EACxC,MAAM,aAAa,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,KAAK,GAAG;EAElE,OAAO,GAAG,KAAK,QAAQ,OAAO,GAAG;CACnC;;;;CAKA,MAAa,KAAK,MAAc,IAA2C;EACzE,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,mBAAmB,sBAAsB;GAGjD,MAAM,aAAa,MAAM,KAAK,cAAc,IAAI,CAAC,CAAC,YAAY,SAAkB;GAGhF,OAAO,KAAK,YAAY,IAAI;GAC5B,KAAK,KAAK,YAAY,EAAE;GAExB,MAAM,UAAU,IAAI,kBAAkB;IACpC,QAAQ,KAAK,QAAQ;IACrB,YAAY,KAAK,WAAW,IAAI;IAChC,KAAK;IACL,GAAI,KAAK,mBAAmB,SAAS,eAAe,YAAY,EAAE,KAAK,cAAuB;GAChG,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAG7C,MAAM,cAAc,IAAI,kBAAkB;IACxC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GACD,MAAM,aAAa,MAAM,KAAK,OAAO,KAAK,WAAW;GAErD,OAAO;IACL,MAAM;IACN,KAAK,KAAK,IAAI,EAAE;IAChB,MAAM,WAAW,iBAAiB;IAClC,MAAM,WAAW,MAAM,QAAQ,MAAM,EAAE,KAAK;IAC5C,UAAU,WAAW,eAAe,KAAK,cAAc,EAAE;IACzD,QAAQ,KAAK;IACb,QAAQ,KAAK,QAAQ;IACrB,QAAQ,KAAK,QAAQ;IACrB,MAAM,OAAO,kBAAkB;IAC/B,WAAW,OAAO;GACpB;EACF,GAAG,MAAM;CACX;;;;CAKA,MAAa,KAAK,MAAc,IAA2C;EACzE,MAAM,OAAO,MAAM,KAAK,KAAK,MAAM,EAAE;EACrC,MAAM,KAAK,OAAO,IAAI;EACtB,OAAO;CACT;;;;CAKA,MAAa,KAAK,WAAmB,SAAmD;EACtF,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,yBAAyB;GAGjC,YAAY,KAAK,YAAY,SAAS;GAGtC,IAAI,aAAa,cAAc,OAAO,CAAC,UAAU,SAAS,GAAG,GAC3D,YAAY,GAAG,UAAU;GAG3B,MAAM,UAAU,IAAI,qBAAqB;IACvC,QAAQ,KAAK,QAAQ;IACrB,QAAQ;IACR,SAAS,SAAS;IAClB,mBAAmB,SAAS;IAC5B,WAAW,SAAS,YAAY,SAAY;GAC9C,CAAC;GAED,MAAM,SAAS,MAAM,KAAK,OAAO,KAAK,OAAO;GAC7C,MAAM,QAA2B,CAAC;GAGlC,KAAK,MAAM,UAAU,OAAO,YAAY,CAAC,GAAG;IAC1C,IAAI,CAAC,OAAO,KAAK;IAEjB,MAAM,KAAK;KACT,MAAM,OAAO;KACb,MAAM,OAAO,IAAI,MAAM,GAAG,CAAC,CAAC,IAAI,KAAK;KACrC,MAAM,OAAO,QAAQ;KACrB,aAAa;KACb,cAAc,OAAO;KACrB,MAAM,OAAO;KACb,cAAc,OAAO;IACvB,CAAC;GACH;GAGA,KAAK,MAAM,UAAU,OAAO,kBAAkB,CAAC,GAAG;IAChD,IAAI,CAAC,OAAO,QAAQ;IAEpB,MAAM,KAAK;KACT,MAAM,OAAO;KACb,MAAM,OAAO,OAAO,MAAM,GAAG,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,IAAI,KAAK;KACxD,MAAM;KACN,aAAa;IACf,CAAC;GACH;GAEA,OAAO;EACT,GAAG,MAAM;CACX;;;;CASA,AAAO,YAAoB;EACzB,OAAO,KAAK,QAAQ;CACtB;;;;CAKA,AAAO,YAAoB;EACzB,OAAO,KAAK,QAAQ;CACtB;;;;CAKA,MAAa,gBAAgB,UAAkB,cAAqC;EAClF,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,sBAAsB;GAG9B,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,kBAAkB;IACpC,QAAQ,KAAK,QAAQ;IACrB,YAAY,KAAK,WAAW,QAAQ;IACpC,KAAK;IACL,cAAc;IACd,mBAAmB;GACrB,CAAC;GAED,MAAM,KAAK,OAAO,KAAK,OAAO;EAChC,GAAG,iBAAiB;CACtB;;;;CAKA,MAAa,cAAc,UAAkB,YAA2C;EACtF,IAAI,KAAK,mBAAmB,OAC1B,MAAM,IAAI,uBAAuB,iBAAiB,KAAK,IAAI;EAG7D,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,wBAAwB;GAGhC,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,oBAAoB;IACtC,QAAQ,KAAK,QAAQ;IACrB,KAAK;IACL,KAAK,eAAe,WAAW,gBAAgB;GACjD,CAAC;GAED,MAAM,KAAK,OAAO,KAAK,OAAO;EAChC,GAAG,eAAe;CACpB;;;;CAKA,MAAa,cAAc,UAA2C;EACpE,OAAO,KAAK,UAAU,YAAY;GAChC,MAAM,EAAE,wBAAwB;GAGhC,WAAW,KAAK,YAAY,QAAQ;GAEpC,MAAM,UAAU,IAAI,oBAAoB;IACtC,QAAQ,KAAK,QAAQ;IACrB,KAAK;GACP,CAAC;GAWD,QANsB,MAHD,KAAK,OAAO,KAAK,OAAO,EAGjB,CAAC,QAAQ,MAClC,UACC,MAAM,SAAS,QAAQ,qDACvB,MAAM,eAAe,MACzB,IAEuB,WAAW;EACpC,GAAG,eAAe;CACpB;;;;CASA,AAAU,cAAc,QAAwB;EAC9C,OAAO,OAAO,WAAW,QAAQ,CAAC,CAAC,OAAO,IAAI,WAAW,MAAM,CAAC,CAAC,CAAC,OAAO,KAAK;CAChF;;;;CAKA,AAAU,cAAc,UAA0B;EAChD,OAAO,YAAY,QAAQ;CAC7B;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CloudStorageDriverOptions } from "../types.mjs";
|
|
2
2
|
import { CloudDriver } from "./cloud-driver.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../../packages/core/src/storage/drivers/do-spaces-driver.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* DigitalOcean Spaces Storage Driver
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"do-spaces-driver.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"do-spaces-driver.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/do-spaces-driver.ts"],"mappings":";;;;;;AA0BA;;;;;;;;;;;;;;;;;;AAgC6B;;cAhChB,cAAA,SAAuB,WAAA,CAAY,yBAAA;;;;WAI9B,IAAA;;;;;;;cAQG,OAAA,EAAS,yBAAA;;;;;;YAWlB,WAAA;;;;;;EASH,GAAA,CAAI,QAAA;AAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CloudDriver } from "./cloud-driver.mjs";
|
|
2
2
|
import { ltrim } from "@mongez/reinforcements";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../../packages/core/src/storage/drivers/do-spaces-driver.ts
|
|
5
5
|
/**
|
|
6
6
|
* DigitalOcean Spaces Storage Driver
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"do-spaces-driver.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"do-spaces-driver.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/do-spaces-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { CloudStorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * DigitalOcean Spaces Storage Driver\n *\n * Spaces is S3-compatible with a different URL structure.\n *\n * URL Patterns:\n * - With urlPrefix: {urlPrefix}/{key}\n * - CDN URL: https://{bucket}.{region}.cdn.digitaloceanspaces.com/{key}\n * - Origin URL: https://{bucket}.{region}.digitaloceanspaces.com/{key}\n *\n * Regions: nyc3, sfo3, ams3, sgp1, fra1, etc.\n *\n * @example\n * ```typescript\n * const driver = new DOSpacesDriver({\n * bucket: \"my-space\",\n * region: \"nyc3\",\n * accessKeyId: process.env.DO_SPACES_KEY,\n * secretAccessKey: process.env.DO_SPACES_SECRET,\n * });\n * ```\n */\nexport class DOSpacesDriver extends CloudDriver<CloudStorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"spaces\";\n\n /**\n * Intentionally NOT supported: unsupported until verified that Spaces\n * honours `If-None-Match: *` atomically. Overriding with `undefined` makes\n * `supportsPutIfAbsent()` false for this driver. The inherited method is\n * shadowed with an own `undefined` property, so it is absent at runtime.\n */\n public constructor(options: CloudStorageDriverOptions) {\n super(options);\n\n (this as { putIfAbsent?: unknown }).putIfAbsent = undefined;\n }\n\n /**\n * Get Spaces endpoint URL\n *\n * Spaces endpoint format: https://{region}.digitaloceanspaces.com\n */\n protected getEndpoint(): string {\n return this.options.endpoint || `https://${this.options.region}.digitaloceanspaces.com`;\n }\n\n /**\n * Get public URL for file\n *\n * Note: DO Spaces includes automatic CDN with the `.cdn.` subdomain\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured — return it directly so the CDN-host\n // URL below is NOT appended (which would yield a double-host URL).\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n return `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Default Spaces CDN URL\n return `https://${this.options.bucket}.${this.options.region}.cdn.digitaloceanspaces.com/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,iBAAb,cAAoC,YAAuC;;;;;;;CAYzE,AAAO,YAAY,SAAoC;EACrD,MAAM,OAAO;cATQ;EAWrB,AAAC,KAAmC,cAAc;CACpD;;;;;;CAOA,AAAU,cAAsB;EAC9B,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,OAAO;CACjE;;;;;;CAOA,AAAO,IAAI,UAA0B;EAGnC,IAAI,KAAK,QAAQ,WAEf,OAAO,GADQ,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACvC,EAAE,GAAG,MAAM,UAAU,GAAG;EAIzC,OAAO,WAAW,KAAK,QAAQ,OAAO,GAAG,KAAK,QAAQ,OAAO,8BAA8B;CAC7F;AACF"}
|
|
@@ -2,7 +2,7 @@ import { DeleteManyResult, ListOptions, LocalStorageDriverOptions, PutOptions, S
|
|
|
2
2
|
import { UploadedFile } from "../../http/uploaded-file.mjs";
|
|
3
3
|
import { Readable } from "stream";
|
|
4
4
|
|
|
5
|
-
//#region
|
|
5
|
+
//#region ../../packages/core/src/storage/drivers/local-driver.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* Local filesystem storage driver
|
|
8
8
|
*
|
|
@@ -88,6 +88,11 @@ declare class LocalDriver implements StorageDriverContract {
|
|
|
88
88
|
deleteDirectory(directoryPath: string, options?: {
|
|
89
89
|
allowRoot?: boolean;
|
|
90
90
|
}): Promise<boolean>;
|
|
91
|
+
/**
|
|
92
|
+
* Every file under `directory`, as absolute paths; empty when it cannot be
|
|
93
|
+
* read. Used to purge the image derivatives of a deleted directory's files.
|
|
94
|
+
*/
|
|
95
|
+
protected listFilesRecursively(directory: string): Promise<string[]>;
|
|
91
96
|
/**
|
|
92
97
|
* Check if file exists
|
|
93
98
|
*/
|
|
@@ -146,6 +151,12 @@ declare class LocalDriver implements StorageDriverContract {
|
|
|
146
151
|
* Get the storage root directory
|
|
147
152
|
*/
|
|
148
153
|
getRoot(): string;
|
|
154
|
+
/**
|
|
155
|
+
* Remove the cached image derivatives of a file that was just deleted or
|
|
156
|
+
* moved away. Best effort: the file operation has already succeeded, so a
|
|
157
|
+
* cache that cannot be cleared is logged, never thrown.
|
|
158
|
+
*/
|
|
159
|
+
protected purgeImageVariants(absolutePath: string): Promise<void>;
|
|
149
160
|
/**
|
|
150
161
|
* Get absolute file path
|
|
151
162
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-driver.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"local-driver.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/local-driver.ts"],"mappings":";;;;;;;;AA6CA;;;;;;cAAa,WAAA,YAAuB,qBAAA;EA0BR,OAAA,EAAS,yBAAA;EAqDvB;;;EAAA,SA3EI,IAAA,EAAM,iBAAA;EA+GV;;;EAAA,UA1GF,IAAA;EA+JE;;;EAAA,UA1JF,SAAA;EA8L0B;;;EAAA,UAzL1B,kBAAA;EAmO4C;;;EAAA,UA9N5C,YAAA;cAEgB,OAAA,GAAS,yBAAA;EAuT4B;;;;;;;;;EAhSxD,WAAA,CAAY,QAAA;EAif4B;;;EAtdlC,GAAA,CACX,IAAA,EAAM,MAAA,YAAkB,YAAA,EACxB,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EA4jBoB;;;;;;;;EA5hBlB,WAAA,CACX,IAAA,EAAM,MAAA,WACN,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EApHuB;;;EAqKrB,SAAA,CACX,MAAA,EAAQ,QAAA,EACR,QAAA,UACA,OAAA,GAAU,UAAA,GACT,OAAA,CAAQ,eAAA;EArKW;;;EAwMT,GAAA,CAAI,QAAA,WAAmB,OAAA,CAAQ,MAAA;EApLlC;;;EAiMG,SAAA,CAAU,QAAA,WAAmB,OAAA,CAAQ,QAAA;EAxK3C;;;EAqLM,MAAA,CAAO,QAAA,WAAmB,OAAA;EAzJb;;;EAyKb,UAAA,CAAW,SAAA,aAAsB,OAAA,CAAQ,gBAAA;EAvKpD;;;;;;;EAiMW,eAAA,CAAgB,aAAA,UAAuB,OAAA;IAAY,SAAA;EAAA,IAAqB,OAAA;EA5J1E;;;;EAAA,UAuLK,oBAAA,CAAqB,SAAA,WAAoB,OAAA;EAnI7C;;;EAkJC,MAAA,CAAO,QAAA,WAAmB,OAAA;EA9G1B;;;EA0HN,GAAA,CAAI,QAAA;EA7GE;;;;;;;EAwHA,YAAA,CAAa,QAAA,UAAkB,SAAA,YAAmB,OAAA;EA3FvC;;;;;;EA6GjB,oBAAA,CAAqB,QAAA,UAAkB,SAAA;EAnFuC;;;;;;EA2GxE,sBAAA,CAAuB,KAAA,WAAgB,OAAA,CAAQ,wBAAA;EArDrD;;;EAiIM,QAAA,CAAS,QAAA,WAAmB,OAAA,CAAQ,eAAA;EAtHL;;;EA6I/B,IAAA,CAAK,QAAA,WAAmB,OAAA;EA3HS;;;EAuIjC,IAAA,CAAK,IAAA,UAAc,EAAA,WAAa,OAAA,CAAQ,eAAA;EA/GO;;;EA2I/C,IAAA,CAAK,IAAA,UAAc,EAAA,WAAa,OAAA,CAAQ,eAAA;EA/DJ;;;EA2FpC,IAAA,CAAK,SAAA,UAAmB,OAAA,GAAU,WAAA,GAAc,OAAA,CAAQ,eAAA;EAxDxD;;;EAwGN,IAAA,CAAK,QAAA;EAxGyC;;;EA+G9C,OAAA;EAnFsC;;;;;EAAA,UAgG7B,kBAAA,CAAmB,YAAA,WAAuB,OAAA;EApEG;;;;;;;EAAA,UAuFnD,eAAA,CAAgB,QAAA;EAAhB;;;EAAA,UAmBM,QAAA,CAAS,IAAA,EAAM,MAAA,YAAkB,YAAA,GAAe,OAAA,CAAQ,MAAA;EAAvB;;;EAAA,UAgBvC,aAAA,CAAc,MAAA,EAAQ,MAAA;EAAtB;;;EAAA,UAOM,QAAA,CAAS,YAAA,WAAuB,OAAA;EAAvB;;;EAAA,UAaf,aAAA,CAAc,QAAA;AAAA"}
|
|
@@ -3,7 +3,9 @@ import { url } from "../../utils/urls.mjs";
|
|
|
3
3
|
import { StorageError } from "../utils/storage-error.mjs";
|
|
4
4
|
import { storageDriverContext } from "../context/storage-driver-context.mjs";
|
|
5
5
|
import { getMimeType } from "../utils/mime.mjs";
|
|
6
|
+
import { purgeImageVariantsOfFile } from "../../http/uploads/image-variant-cache.mjs";
|
|
6
7
|
import { resolveWithinRoot } from "../utils/contain-path.mjs";
|
|
8
|
+
import { log } from "@warlock.js/logger";
|
|
7
9
|
import { basename, dirname, join, resolve } from "path";
|
|
8
10
|
import { ltrim } from "@mongez/reinforcements";
|
|
9
11
|
import { directoryExistsAsync, ensureDirectoryAsync, fileExistsAsync, removeDirectoryAsync, unlinkAsync } from "@warlock.js/fs";
|
|
@@ -13,7 +15,7 @@ import crypto from "crypto";
|
|
|
13
15
|
import { Transform } from "stream";
|
|
14
16
|
import { pipeline } from "stream/promises";
|
|
15
17
|
|
|
16
|
-
//#region
|
|
18
|
+
//#region ../../packages/core/src/storage/drivers/local-driver.ts
|
|
17
19
|
/**
|
|
18
20
|
* Local filesystem storage driver
|
|
19
21
|
*
|
|
@@ -153,6 +155,7 @@ var LocalDriver = class {
|
|
|
153
155
|
const absolutePath = this.getAbsolutePath(location);
|
|
154
156
|
if (!await fileExistsAsync(absolutePath)) return false;
|
|
155
157
|
await unlinkAsync(absolutePath);
|
|
158
|
+
await this.purgeImageVariants(absolutePath);
|
|
156
159
|
return true;
|
|
157
160
|
}
|
|
158
161
|
/**
|
|
@@ -185,10 +188,26 @@ var LocalDriver = class {
|
|
|
185
188
|
async deleteDirectory(directoryPath, options) {
|
|
186
189
|
const absolutePath = this.getAbsolutePath(directoryPath);
|
|
187
190
|
if (!options?.allowRoot && resolve(absolutePath) === this.root) throw new StorageError(`Refusing to delete the storage root ("${directoryPath}"). Pass { allowRoot: true } to confirm.`, { context: { directoryPath } });
|
|
191
|
+
const files = await this.listFilesRecursively(absolutePath);
|
|
188
192
|
await removeDirectoryAsync(absolutePath);
|
|
193
|
+
for (const file of files) await this.purgeImageVariants(file);
|
|
189
194
|
return true;
|
|
190
195
|
}
|
|
191
196
|
/**
|
|
197
|
+
* Every file under `directory`, as absolute paths; empty when it cannot be
|
|
198
|
+
* read. Used to purge the image derivatives of a deleted directory's files.
|
|
199
|
+
*/
|
|
200
|
+
async listFilesRecursively(directory) {
|
|
201
|
+
try {
|
|
202
|
+
return (await readdir(directory, {
|
|
203
|
+
recursive: true,
|
|
204
|
+
withFileTypes: true
|
|
205
|
+
})).filter((entry) => entry.isFile()).map((entry) => join(entry.parentPath, entry.name));
|
|
206
|
+
} catch {
|
|
207
|
+
return [];
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
192
211
|
* Check if file exists
|
|
193
212
|
*/
|
|
194
213
|
async exists(location) {
|
|
@@ -338,6 +357,7 @@ var LocalDriver = class {
|
|
|
338
357
|
if (!await fileExistsAsync(fromPath)) throw new Error(`Source file not found: ${from}`);
|
|
339
358
|
await ensureDirectoryAsync(dirname(toPath));
|
|
340
359
|
await rename(fromPath, toPath);
|
|
360
|
+
await this.purgeImageVariants(fromPath);
|
|
341
361
|
const hash = await this.hashFile(toPath);
|
|
342
362
|
const stats = await stat(toPath);
|
|
343
363
|
return {
|
|
@@ -389,6 +409,18 @@ var LocalDriver = class {
|
|
|
389
409
|
return this.root;
|
|
390
410
|
}
|
|
391
411
|
/**
|
|
412
|
+
* Remove the cached image derivatives of a file that was just deleted or
|
|
413
|
+
* moved away. Best effort: the file operation has already succeeded, so a
|
|
414
|
+
* cache that cannot be cleared is logged, never thrown.
|
|
415
|
+
*/
|
|
416
|
+
async purgeImageVariants(absolutePath) {
|
|
417
|
+
try {
|
|
418
|
+
await purgeImageVariantsOfFile(this.root, absolutePath);
|
|
419
|
+
} catch (error) {
|
|
420
|
+
log.warn("storage.local", "purge-image-variants", `Could not remove cached image variants: ${error instanceof Error ? error.message : String(error)}`);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
/**
|
|
392
424
|
* Get absolute file path
|
|
393
425
|
*
|
|
394
426
|
* Routes through {@link resolveWithinRoot} so a location can never escape
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"local-driver.mjs","names":["fsPromises"],"sources":["../../../../../../../../core/src/storage/drivers/local-driver.ts"],"sourcesContent":["import {\n directoryExistsAsync,\n ensureDirectoryAsync,\n fileExistsAsync,\n removeDirectoryAsync,\n unlinkAsync,\n} from \"@warlock.js/fs\";\nimport { ltrim } from \"@mongez/reinforcements\";\nimport crypto from \"crypto\";\nimport { createReadStream, createWriteStream, promises as fsPromises } from \"fs\";\nimport { copyFile, readFile, readdir, rename, stat, unlink, writeFile } from \"fs/promises\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { Transform, type Readable } from \"stream\";\nimport { pipeline } from \"stream/promises\";\nimport { UploadedFile } from \"../../http\";\nimport { storagePath } from \"../../utils/paths\";\nimport { url } from \"../../utils/urls\";\nimport { storageDriverContext } from \"../context/storage-driver-context\";\nimport { resolveWithinRoot } from \"../utils/contain-path\";\nimport { StorageError } from \"../utils/storage-error\";\nimport type {\n DeleteManyResult,\n ListOptions,\n LocalStorageDriverOptions,\n PutOptions,\n StorageDriverContract,\n StorageDriverType,\n StorageFileData,\n StorageFileInfo,\n TemporaryTokenPayload,\n TemporaryTokenValidation,\n} from \"../types\";\nimport { getMimeType } from \"../utils/mime\";\n\n/**\n * Local filesystem storage driver\n *\n * Stores files on the local filesystem with support for:\n * - File operations (put, get, delete, copy, move)\n * - Stream operations for large files\n * - Batch operations\n * - Signed temporary URLs\n */\nexport class LocalDriver implements StorageDriverContract {\n /**\n * Driver name\n */\n public readonly name: StorageDriverType = \"local\";\n\n /**\n * Root path for storage\n */\n protected root: string;\n\n /**\n * URL prefix for file URLs\n */\n protected urlPrefix: string = \"\";\n\n /**\n * URL prefix for temporary file URLs\n */\n protected temporaryUrlPrefix: string;\n\n /**\n * Secret key for signing temporary URLs\n */\n protected signatureKey?: string;\n\n public constructor(public options: LocalStorageDriverOptions = {}) {\n // Resolve the root to an absolute, normalized path up front so the\n // path-traversal containment check (resolveWithinRoot) has a stable\n // anchor to compare resolved locations against.\n this.root = resolve(options.root ?? storagePath());\n this.urlPrefix = options.urlPrefix ?? \"\";\n this.temporaryUrlPrefix = options.temporaryUrlPrefix ?? \"/temp-files\";\n this.signatureKey = options.signatureKey;\n }\n\n // ============================================================\n // Prefix Operations\n // ============================================================\n\n /**\n * Apply prefix to location path\n *\n * Priority: context prefix > driver options prefix > no prefix\n * This allows multi-tenant scenarios where context overrides driver config.\n *\n * @param location - Original location path\n * @returns Location with prefix applied if one exists\n */\n public applyPrefix(location: string): string {\n // Check context prefix first (highest priority)\n const contextPrefix = storageDriverContext.getPrefix();\n const prefix = contextPrefix || this.options.prefix;\n\n if (!prefix) {\n return location;\n }\n\n const cleanPrefix = prefix.replace(/\\/+$/, \"\");\n const cleanLocation = location.replace(/^\\/+/, \"\");\n\n // Avoid double-prefixing\n if (cleanLocation.startsWith(cleanPrefix + \"/\") || cleanLocation === cleanPrefix) {\n return cleanLocation;\n }\n\n return `${cleanPrefix}/${cleanLocation}`;\n }\n\n // ============================================================\n // Core File Operations\n // ============================================================\n\n /**\n * Put file to local storage\n */\n public async put(\n file: Buffer | string | UploadedFile,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData> {\n const absolutePath = this.getAbsolutePath(location);\n\n await ensureDirectoryAsync(dirname(absolutePath));\n\n const fileBuffer = await this.toBuffer(file);\n const hash = this.calculateHash(fileBuffer);\n\n await writeFile(absolutePath, new Uint8Array(fileBuffer));\n\n\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: this.applyPrefix(location),\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Atomically put a file only if nothing exists at `location`.\n *\n * Content is written to a temp file in the same directory, then hard-linked\n * to the target. `link()` fails with EEXIST if the target exists, so exactly\n * one concurrent caller wins, the object never appears half-written, and the\n * check is atomic on NFS too. Returns `null` only on EEXIST; other errors throw.\n */\n public async putIfAbsent(\n file: Buffer | string,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData | null> {\n const absolutePath = this.getAbsolutePath(location);\n const directory = dirname(absolutePath);\n\n await ensureDirectoryAsync(directory);\n\n // Unlike put(), a string here is CONTENT, never a source path (matches\n // the cloud driver): the objects this protects are small JSON bodies.\n const fileBuffer = typeof file === \"string\" ? Buffer.from(file) : file;\n const hash = this.calculateHash(fileBuffer);\n\n const tempPath = join(\n directory,\n `.${basename(absolutePath)}.${crypto.randomBytes(8).toString(\"hex\")}.tmp`,\n );\n\n try {\n await writeFile(tempPath, new Uint8Array(fileBuffer));\n\n try {\n await fsPromises.link(tempPath, absolutePath);\n } catch (error: any) {\n if (error?.code === \"EEXIST\") {\n return null;\n }\n\n throw error;\n }\n } finally {\n await unlink(tempPath).catch(() => undefined);\n }\n\n\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: this.applyPrefix(location),\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Put file from a readable stream (for large files)\n */\n public async putStream(\n stream: Readable,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData> {\n const absolutePath = this.getAbsolutePath(location);\n\n await ensureDirectoryAsync(dirname(absolutePath));\n\n // Hash while streaming so large files are never read back into memory\n const hasher = crypto.createHash(\"sha256\");\n const hashTransform = new Transform({\n transform(chunk, _encoding, callback) {\n hasher.update(chunk);\n callback(null, chunk);\n },\n });\n\n const writeStream = createWriteStream(absolutePath);\n await pipeline(stream, hashTransform, writeStream);\n\n\n const hash = hasher.digest(\"hex\");\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: this.applyPrefix(location),\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Get file contents as Buffer\n */\n public async get(location: string): Promise<Buffer> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${location}`);\n }\n\n return readFile(absolutePath);\n }\n\n /**\n * Get file as a readable stream (for large files)\n */\n public async getStream(location: string): Promise<Readable> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${location}`);\n }\n\n return createReadStream(absolutePath);\n }\n\n /**\n * Delete a file\n */\n public async delete(location: string): Promise<boolean> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n return false;\n }\n\n await unlinkAsync(absolutePath);\n\n\n return true;\n }\n\n /**\n * Delete multiple files at once\n */\n public async deleteMany(locations: string[]): Promise<DeleteManyResult[]> {\n const results: DeleteManyResult[] = [];\n\n for (const location of locations) {\n try {\n const deleted = await this.delete(location);\n results.push({ location, deleted });\n } catch (error) {\n results.push({\n location,\n deleted: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }\n\n return results;\n }\n\n /**\n * Delete directory\n *\n * The directory path is resolved through {@link getAbsolutePath} so it is\n * contained within the storage root — the raw, caller-supplied argument is\n * never handed to the filesystem (preventing `../` traversal deletes).\n */\n public async deleteDirectory(directoryPath: string, options?: { allowRoot?: boolean }) {\n const absolutePath = this.getAbsolutePath(directoryPath);\n\n if (!options?.allowRoot && resolve(absolutePath) === this.root) {\n throw new StorageError(\n `Refusing to delete the storage root (\"${directoryPath}\"). Pass { allowRoot: true } to confirm.`,\n { context: { directoryPath } },\n );\n }\n\n await removeDirectoryAsync(absolutePath);\n\n return true;\n }\n\n /**\n * Check if file exists\n */\n public async exists(location: string): Promise<boolean> {\n const absolutePath = this.getAbsolutePath(location);\n return Boolean(await fileExistsAsync(absolutePath));\n }\n\n // ============================================================\n // URL Operations\n // ============================================================\n\n /**\n * Get public URL for file\n */\n public url(location: string): string {\n return url(this.urlPrefix + \"/\" + ltrim(this.applyPrefix(location), \"/\"));\n }\n\n /**\n * Get a temporary signed URL that expires\n * Returns a clean URL with encoded token: {temporaryUrlPrefix}/{token}\n *\n * @param location - File path\n * @param expiresIn - Seconds until expiration (default: 3600)\n */\n public async temporaryUrl(location: string, expiresIn = 3600): Promise<string> {\n if (!this.signatureKey) {\n throw new Error(\n \"Temporary URLs require a signatureKey in LocalDriver options. \" +\n \"Configure storage.drivers.local.signatureKey in your config.\",\n );\n }\n\n const token = this.encodeTemporaryToken(location, expiresIn);\n return `${this.temporaryUrlPrefix}/${token}`;\n }\n\n /**\n * Encode a temporary token containing path, expiry, and signature\n *\n * @param location - File path\n * @param expiresIn - Seconds until expiration\n */\n public encodeTemporaryToken(location: string, expiresIn: number): string {\n if (!this.signatureKey) {\n throw new Error(\"Temporary tokens require a signatureKey\");\n }\n\n const exp = Math.floor(Date.now() / 1000) + expiresIn;\n const sig = crypto\n .createHmac(\"sha256\", this.signatureKey)\n .update(`${location}:${exp}`)\n .digest(\"hex\");\n\n const payload: TemporaryTokenPayload = { path: location, exp, sig };\n const json = JSON.stringify(payload);\n\n // Use base64url encoding (URL-safe base64)\n return Buffer.from(json).toString(\"base64url\");\n }\n\n /**\n * Validate a temporary URL token\n * Returns a result object with validation status, file info, and convenience methods\n *\n * @param token - The token from the URL\n */\n public async validateTemporaryToken(token: string): Promise<TemporaryTokenValidation> {\n // Check signature key\n if (!this.signatureKey) {\n return { valid: false, error: \"missing_key\" };\n }\n\n // Decode token\n let payload: TemporaryTokenPayload;\n try {\n const json = Buffer.from(token, \"base64url\").toString(\"utf-8\");\n payload = JSON.parse(json);\n } catch {\n return { valid: false, error: \"invalid_token\" };\n }\n\n // Validate payload structure\n if (!payload.path || !payload.exp || !payload.sig) {\n return { valid: false, error: \"invalid_token\" };\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (payload.exp < now) {\n return { valid: false, error: \"expired\" };\n }\n\n // Verify signature\n const expectedSig = crypto\n .createHmac(\"sha256\", this.signatureKey)\n .update(`${payload.path}:${payload.exp}`)\n .digest(\"hex\");\n\n const sigBuffer = Buffer.from(payload.sig, \"hex\");\n const expectedBuffer = Buffer.from(expectedSig, \"hex\");\n\n if (sigBuffer.length !== expectedBuffer.length) {\n return { valid: false, error: \"invalid_signature\" };\n }\n\n const isValidSig = crypto.timingSafeEqual(\n new Uint8Array(sigBuffer),\n new Uint8Array(expectedBuffer),\n );\n\n if (!isValidSig) {\n return { valid: false, error: \"invalid_signature\" };\n }\n\n // Check file exists\n const absolutePath = this.getAbsolutePath(payload.path);\n if (!(await fileExistsAsync(absolutePath))) {\n return { valid: false, error: \"file_not_found\" };\n }\n\n // Build successful result with convenience methods\n const result: TemporaryTokenValidation = {\n valid: true,\n path: payload.path,\n absolutePath,\n expiresAt: new Date(payload.exp * 1000),\n mimeType: this.guessMimeType(payload.path),\n driver: this,\n getFile: () => this.get(payload.path),\n getStream: () => this.getStream(payload.path),\n };\n\n return result;\n }\n\n // ============================================================\n // Metadata Operations\n // ============================================================\n\n /**\n * Get file info/metadata without downloading\n */\n public async metadata(location: string): Promise<StorageFileInfo> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${absolutePath}`);\n }\n\n const stats = await stat(absolutePath);\n const name = location.split(\"/\").pop() || \"\";\n\n return {\n path: location,\n name,\n size: stats.size,\n isDirectory: stats.isDirectory(),\n lastModified: stats.mtime,\n mimeType: this.guessMimeType(location),\n };\n }\n\n /**\n * Get file size in bytes (shortcut for metadata().size)\n */\n public async size(location: string): Promise<number> {\n const metadata = await this.metadata(location);\n return metadata.size;\n }\n\n // ============================================================\n // File Operations\n // ============================================================\n\n /**\n * Copy file to a new location\n */\n public async copy(from: string, to: string): Promise<StorageFileData> {\n const fromPath = this.getAbsolutePath(from);\n const toPath = this.getAbsolutePath(to);\n\n if (!(await fileExistsAsync(fromPath))) {\n throw new Error(`Source file not found: ${from}`);\n }\n\n await ensureDirectoryAsync(dirname(toPath));\n await copyFile(fromPath, toPath);\n\n\n const hash = await this.hashFile(toPath);\n const stats = await stat(toPath);\n\n return {\n path: this.applyPrefix(to),\n url: this.url(to),\n size: stats.size,\n hash,\n mimeType: this.guessMimeType(to),\n driver: this.name,\n };\n }\n\n /**\n * Move file to a new location\n */\n public async move(from: string, to: string): Promise<StorageFileData> {\n const fromPath = this.getAbsolutePath(from);\n const toPath = this.getAbsolutePath(to);\n\n if (!(await fileExistsAsync(fromPath))) {\n throw new Error(`Source file not found: ${from}`);\n }\n\n await ensureDirectoryAsync(dirname(toPath));\n await rename(fromPath, toPath);\n\n\n const hash = await this.hashFile(toPath);\n const stats = await stat(toPath);\n\n return {\n path: this.applyPrefix(to),\n url: this.url(to),\n size: stats.size,\n hash,\n mimeType: this.guessMimeType(to),\n driver: this.name,\n };\n }\n\n /**\n * List files in a directory\n */\n public async list(directory: string, options?: ListOptions): Promise<StorageFileInfo[]> {\n const absolutePath = this.getAbsolutePath(directory);\n const files: StorageFileInfo[] = [];\n\n // A listing target is a DIRECTORY, so guard with `directoryExistsAsync`.\n // `fileExistsAsync` resolves `false` for a folder, which would make `list`\n // always return [] for a real, populated directory.\n if (!(await directoryExistsAsync(absolutePath))) {\n return files;\n }\n\n const entries = await readdir(absolutePath, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = join(directory, entry.name);\n const entryStats = await stat(this.getAbsolutePath(entryPath));\n\n files.push({\n path: entryPath,\n name: entry.name,\n size: entryStats.size,\n isDirectory: entry.isDirectory(),\n lastModified: entryStats.mtime,\n mimeType: entry.isFile() ? this.guessMimeType(entry.name) : undefined,\n });\n\n // Recursively list subdirectories if requested\n if (options?.recursive && entry.isDirectory()) {\n const subFiles = await this.list(entryPath, options);\n files.push(...subFiles);\n }\n\n // Respect limit\n if (options?.limit && files.length >= options.limit) {\n break;\n }\n }\n\n return files;\n }\n\n // ============================================================\n // Path Operations\n // ============================================================\n\n /**\n * Get absolute filesystem path for a location\n */\n public path(location: string): string {\n return this.getAbsolutePath(location);\n }\n\n /**\n * Get the storage root directory\n */\n public getRoot(): string {\n return this.root;\n }\n\n // ============================================================\n // Utilities\n // ============================================================\n\n /**\n * Get absolute file path\n *\n * Routes through {@link resolveWithinRoot} so a location can never escape\n * the configured storage root via `..` traversal, an absolute path, or a\n * prefix breakout.\n */\n protected getAbsolutePath(location: string): string {\n const prefixedLocation = this.applyPrefix(location);\n const resolved = resolveWithinRoot(this.root, prefixedLocation);\n\n // The prefix is a containment boundary too: \"../t2/x\" under prefix \"t1\"\n // must not land in a sibling tenant's directory.\n const prefix = storageDriverContext.getPrefix() || this.options.prefix;\n\n if (prefix) {\n const prefixRoot = resolveWithinRoot(this.root, prefix.replace(/^[\\\\/]+|[\\\\/]+$/g, \"\"));\n resolveWithinRoot(prefixRoot, resolved);\n }\n\n return resolved;\n }\n\n /**\n * Convert various input types to Buffer\n */\n protected async toBuffer(file: Buffer | string | UploadedFile): Promise<Buffer> {\n if (Buffer.isBuffer(file)) {\n return file;\n }\n\n // A string is always content, never a source path\n if (typeof file === \"string\") {\n return Buffer.from(file);\n }\n\n return file.buffer();\n }\n\n /**\n * Calculate SHA-256 hash\n */\n protected calculateHash(buffer: Buffer): string {\n return crypto.createHash(\"sha256\").update(new Uint8Array(buffer)).digest(\"hex\");\n }\n\n /**\n * Calculate SHA-256 hash of a file by streaming it (constant memory)\n */\n protected async hashFile(absolutePath: string): Promise<string> {\n const hasher = crypto.createHash(\"sha256\");\n\n for await (const chunk of createReadStream(absolutePath)) {\n hasher.update(chunk);\n }\n\n return hasher.digest(\"hex\");\n }\n\n /**\n * Guess MIME type from file extension\n */\n protected guessMimeType(location: string): string {\n return getMimeType(location);\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"local-driver.mjs","names":["fsPromises"],"sources":["../../../../../../../../../packages/core/src/storage/drivers/local-driver.ts"],"sourcesContent":["import {\n directoryExistsAsync,\n ensureDirectoryAsync,\n fileExistsAsync,\n removeDirectoryAsync,\n unlinkAsync,\n} from \"@warlock.js/fs\";\nimport { ltrim } from \"@mongez/reinforcements\";\nimport crypto from \"crypto\";\nimport { createReadStream, createWriteStream, promises as fsPromises } from \"fs\";\nimport { copyFile, readFile, readdir, rename, stat, unlink, writeFile } from \"fs/promises\";\nimport { basename, dirname, join, resolve } from \"path\";\nimport { Transform, type Readable } from \"stream\";\nimport { pipeline } from \"stream/promises\";\nimport { log } from \"@warlock.js/logger\";\nimport { UploadedFile } from \"../../http\";\nimport { purgeImageVariantsOfFile } from \"../../http/uploads/image-variant-cache\";\nimport { storagePath } from \"../../utils/paths\";\nimport { url } from \"../../utils/urls\";\nimport { storageDriverContext } from \"../context/storage-driver-context\";\nimport { resolveWithinRoot } from \"../utils/contain-path\";\nimport { StorageError } from \"../utils/storage-error\";\nimport type {\n DeleteManyResult,\n ListOptions,\n LocalStorageDriverOptions,\n PutOptions,\n StorageDriverContract,\n StorageDriverType,\n StorageFileData,\n StorageFileInfo,\n TemporaryTokenPayload,\n TemporaryTokenValidation,\n} from \"../types\";\nimport { getMimeType } from \"../utils/mime\";\n\n/**\n * Local filesystem storage driver\n *\n * Stores files on the local filesystem with support for:\n * - File operations (put, get, delete, copy, move)\n * - Stream operations for large files\n * - Batch operations\n * - Signed temporary URLs\n */\nexport class LocalDriver implements StorageDriverContract {\n /**\n * Driver name\n */\n public readonly name: StorageDriverType = \"local\";\n\n /**\n * Root path for storage\n */\n protected root: string;\n\n /**\n * URL prefix for file URLs\n */\n protected urlPrefix: string = \"\";\n\n /**\n * URL prefix for temporary file URLs\n */\n protected temporaryUrlPrefix: string;\n\n /**\n * Secret key for signing temporary URLs\n */\n protected signatureKey?: string;\n\n public constructor(public options: LocalStorageDriverOptions = {}) {\n // Resolve the root to an absolute, normalized path up front so the\n // path-traversal containment check (resolveWithinRoot) has a stable\n // anchor to compare resolved locations against.\n this.root = resolve(options.root ?? storagePath());\n this.urlPrefix = options.urlPrefix ?? \"\";\n this.temporaryUrlPrefix = options.temporaryUrlPrefix ?? \"/temp-files\";\n this.signatureKey = options.signatureKey;\n }\n\n // ============================================================\n // Prefix Operations\n // ============================================================\n\n /**\n * Apply prefix to location path\n *\n * Priority: context prefix > driver options prefix > no prefix\n * This allows multi-tenant scenarios where context overrides driver config.\n *\n * @param location - Original location path\n * @returns Location with prefix applied if one exists\n */\n public applyPrefix(location: string): string {\n // Check context prefix first (highest priority)\n const contextPrefix = storageDriverContext.getPrefix();\n const prefix = contextPrefix || this.options.prefix;\n\n if (!prefix) {\n return location;\n }\n\n const cleanPrefix = prefix.replace(/\\/+$/, \"\");\n const cleanLocation = location.replace(/^\\/+/, \"\");\n\n // Avoid double-prefixing\n if (cleanLocation.startsWith(cleanPrefix + \"/\") || cleanLocation === cleanPrefix) {\n return cleanLocation;\n }\n\n return `${cleanPrefix}/${cleanLocation}`;\n }\n\n // ============================================================\n // Core File Operations\n // ============================================================\n\n /**\n * Put file to local storage\n */\n public async put(\n file: Buffer | string | UploadedFile,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData> {\n const absolutePath = this.getAbsolutePath(location);\n\n await ensureDirectoryAsync(dirname(absolutePath));\n\n const fileBuffer = await this.toBuffer(file);\n const hash = this.calculateHash(fileBuffer);\n\n await writeFile(absolutePath, new Uint8Array(fileBuffer));\n\n\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: this.applyPrefix(location),\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Atomically put a file only if nothing exists at `location`.\n *\n * Content is written to a temp file in the same directory, then hard-linked\n * to the target. `link()` fails with EEXIST if the target exists, so exactly\n * one concurrent caller wins, the object never appears half-written, and the\n * check is atomic on NFS too. Returns `null` only on EEXIST; other errors throw.\n */\n public async putIfAbsent(\n file: Buffer | string,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData | null> {\n const absolutePath = this.getAbsolutePath(location);\n const directory = dirname(absolutePath);\n\n await ensureDirectoryAsync(directory);\n\n // Unlike put(), a string here is CONTENT, never a source path (matches\n // the cloud driver): the objects this protects are small JSON bodies.\n const fileBuffer = typeof file === \"string\" ? Buffer.from(file) : file;\n const hash = this.calculateHash(fileBuffer);\n\n const tempPath = join(\n directory,\n `.${basename(absolutePath)}.${crypto.randomBytes(8).toString(\"hex\")}.tmp`,\n );\n\n try {\n await writeFile(tempPath, new Uint8Array(fileBuffer));\n\n try {\n await fsPromises.link(tempPath, absolutePath);\n } catch (error: any) {\n if (error?.code === \"EEXIST\") {\n return null;\n }\n\n throw error;\n }\n } finally {\n await unlink(tempPath).catch(() => undefined);\n }\n\n\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: this.applyPrefix(location),\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Put file from a readable stream (for large files)\n */\n public async putStream(\n stream: Readable,\n location: string,\n options?: PutOptions,\n ): Promise<StorageFileData> {\n const absolutePath = this.getAbsolutePath(location);\n\n await ensureDirectoryAsync(dirname(absolutePath));\n\n // Hash while streaming so large files are never read back into memory\n const hasher = crypto.createHash(\"sha256\");\n const hashTransform = new Transform({\n transform(chunk, _encoding, callback) {\n hasher.update(chunk);\n callback(null, chunk);\n },\n });\n\n const writeStream = createWriteStream(absolutePath);\n await pipeline(stream, hashTransform, writeStream);\n\n\n const hash = hasher.digest(\"hex\");\n const stats = await stat(absolutePath);\n const mimeType = options?.mimeType || this.guessMimeType(location);\n\n return {\n path: this.applyPrefix(location),\n url: this.url(location),\n size: stats.size,\n hash,\n mimeType,\n driver: this.name,\n };\n }\n\n /**\n * Get file contents as Buffer\n */\n public async get(location: string): Promise<Buffer> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${location}`);\n }\n\n return readFile(absolutePath);\n }\n\n /**\n * Get file as a readable stream (for large files)\n */\n public async getStream(location: string): Promise<Readable> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${location}`);\n }\n\n return createReadStream(absolutePath);\n }\n\n /**\n * Delete a file\n */\n public async delete(location: string): Promise<boolean> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n return false;\n }\n\n await unlinkAsync(absolutePath);\n await this.purgeImageVariants(absolutePath);\n\n return true;\n }\n\n /**\n * Delete multiple files at once\n */\n public async deleteMany(locations: string[]): Promise<DeleteManyResult[]> {\n const results: DeleteManyResult[] = [];\n\n for (const location of locations) {\n try {\n const deleted = await this.delete(location);\n results.push({ location, deleted });\n } catch (error) {\n results.push({\n location,\n deleted: false,\n error: error instanceof Error ? error.message : \"Unknown error\",\n });\n }\n }\n\n return results;\n }\n\n /**\n * Delete directory\n *\n * The directory path is resolved through {@link getAbsolutePath} so it is\n * contained within the storage root — the raw, caller-supplied argument is\n * never handed to the filesystem (preventing `../` traversal deletes).\n */\n public async deleteDirectory(directoryPath: string, options?: { allowRoot?: boolean }) {\n const absolutePath = this.getAbsolutePath(directoryPath);\n\n if (!options?.allowRoot && resolve(absolutePath) === this.root) {\n throw new StorageError(\n `Refusing to delete the storage root (\"${directoryPath}\"). Pass { allowRoot: true } to confirm.`,\n { context: { directoryPath } },\n );\n }\n\n // Listed before the delete: once the directory is gone there is nothing\n // left to tell which files had cached image derivatives.\n const files = await this.listFilesRecursively(absolutePath);\n\n await removeDirectoryAsync(absolutePath);\n\n for (const file of files) {\n await this.purgeImageVariants(file);\n }\n\n return true;\n }\n\n /**\n * Every file under `directory`, as absolute paths; empty when it cannot be\n * read. Used to purge the image derivatives of a deleted directory's files.\n */\n protected async listFilesRecursively(directory: string): Promise<string[]> {\n try {\n const entries = await readdir(directory, { recursive: true, withFileTypes: true });\n\n return entries\n .filter((entry) => entry.isFile())\n .map((entry) => join(entry.parentPath, entry.name));\n } catch {\n return [];\n }\n }\n\n /**\n * Check if file exists\n */\n public async exists(location: string): Promise<boolean> {\n const absolutePath = this.getAbsolutePath(location);\n return Boolean(await fileExistsAsync(absolutePath));\n }\n\n // ============================================================\n // URL Operations\n // ============================================================\n\n /**\n * Get public URL for file\n */\n public url(location: string): string {\n return url(this.urlPrefix + \"/\" + ltrim(this.applyPrefix(location), \"/\"));\n }\n\n /**\n * Get a temporary signed URL that expires\n * Returns a clean URL with encoded token: {temporaryUrlPrefix}/{token}\n *\n * @param location - File path\n * @param expiresIn - Seconds until expiration (default: 3600)\n */\n public async temporaryUrl(location: string, expiresIn = 3600): Promise<string> {\n if (!this.signatureKey) {\n throw new Error(\n \"Temporary URLs require a signatureKey in LocalDriver options. \" +\n \"Configure storage.drivers.local.signatureKey in your config.\",\n );\n }\n\n const token = this.encodeTemporaryToken(location, expiresIn);\n return `${this.temporaryUrlPrefix}/${token}`;\n }\n\n /**\n * Encode a temporary token containing path, expiry, and signature\n *\n * @param location - File path\n * @param expiresIn - Seconds until expiration\n */\n public encodeTemporaryToken(location: string, expiresIn: number): string {\n if (!this.signatureKey) {\n throw new Error(\"Temporary tokens require a signatureKey\");\n }\n\n const exp = Math.floor(Date.now() / 1000) + expiresIn;\n const sig = crypto\n .createHmac(\"sha256\", this.signatureKey)\n .update(`${location}:${exp}`)\n .digest(\"hex\");\n\n const payload: TemporaryTokenPayload = { path: location, exp, sig };\n const json = JSON.stringify(payload);\n\n // Use base64url encoding (URL-safe base64)\n return Buffer.from(json).toString(\"base64url\");\n }\n\n /**\n * Validate a temporary URL token\n * Returns a result object with validation status, file info, and convenience methods\n *\n * @param token - The token from the URL\n */\n public async validateTemporaryToken(token: string): Promise<TemporaryTokenValidation> {\n // Check signature key\n if (!this.signatureKey) {\n return { valid: false, error: \"missing_key\" };\n }\n\n // Decode token\n let payload: TemporaryTokenPayload;\n try {\n const json = Buffer.from(token, \"base64url\").toString(\"utf-8\");\n payload = JSON.parse(json);\n } catch {\n return { valid: false, error: \"invalid_token\" };\n }\n\n // Validate payload structure\n if (!payload.path || !payload.exp || !payload.sig) {\n return { valid: false, error: \"invalid_token\" };\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (payload.exp < now) {\n return { valid: false, error: \"expired\" };\n }\n\n // Verify signature\n const expectedSig = crypto\n .createHmac(\"sha256\", this.signatureKey)\n .update(`${payload.path}:${payload.exp}`)\n .digest(\"hex\");\n\n const sigBuffer = Buffer.from(payload.sig, \"hex\");\n const expectedBuffer = Buffer.from(expectedSig, \"hex\");\n\n if (sigBuffer.length !== expectedBuffer.length) {\n return { valid: false, error: \"invalid_signature\" };\n }\n\n const isValidSig = crypto.timingSafeEqual(\n new Uint8Array(sigBuffer),\n new Uint8Array(expectedBuffer),\n );\n\n if (!isValidSig) {\n return { valid: false, error: \"invalid_signature\" };\n }\n\n // Check file exists\n const absolutePath = this.getAbsolutePath(payload.path);\n if (!(await fileExistsAsync(absolutePath))) {\n return { valid: false, error: \"file_not_found\" };\n }\n\n // Build successful result with convenience methods\n const result: TemporaryTokenValidation = {\n valid: true,\n path: payload.path,\n absolutePath,\n expiresAt: new Date(payload.exp * 1000),\n mimeType: this.guessMimeType(payload.path),\n driver: this,\n getFile: () => this.get(payload.path),\n getStream: () => this.getStream(payload.path),\n };\n\n return result;\n }\n\n // ============================================================\n // Metadata Operations\n // ============================================================\n\n /**\n * Get file info/metadata without downloading\n */\n public async metadata(location: string): Promise<StorageFileInfo> {\n const absolutePath = this.getAbsolutePath(location);\n\n if (!(await fileExistsAsync(absolutePath))) {\n throw new Error(`File not found: ${absolutePath}`);\n }\n\n const stats = await stat(absolutePath);\n const name = location.split(\"/\").pop() || \"\";\n\n return {\n path: location,\n name,\n size: stats.size,\n isDirectory: stats.isDirectory(),\n lastModified: stats.mtime,\n mimeType: this.guessMimeType(location),\n };\n }\n\n /**\n * Get file size in bytes (shortcut for metadata().size)\n */\n public async size(location: string): Promise<number> {\n const metadata = await this.metadata(location);\n return metadata.size;\n }\n\n // ============================================================\n // File Operations\n // ============================================================\n\n /**\n * Copy file to a new location\n */\n public async copy(from: string, to: string): Promise<StorageFileData> {\n const fromPath = this.getAbsolutePath(from);\n const toPath = this.getAbsolutePath(to);\n\n if (!(await fileExistsAsync(fromPath))) {\n throw new Error(`Source file not found: ${from}`);\n }\n\n await ensureDirectoryAsync(dirname(toPath));\n await copyFile(fromPath, toPath);\n\n\n const hash = await this.hashFile(toPath);\n const stats = await stat(toPath);\n\n return {\n path: this.applyPrefix(to),\n url: this.url(to),\n size: stats.size,\n hash,\n mimeType: this.guessMimeType(to),\n driver: this.name,\n };\n }\n\n /**\n * Move file to a new location\n */\n public async move(from: string, to: string): Promise<StorageFileData> {\n const fromPath = this.getAbsolutePath(from);\n const toPath = this.getAbsolutePath(to);\n\n if (!(await fileExistsAsync(fromPath))) {\n throw new Error(`Source file not found: ${from}`);\n }\n\n await ensureDirectoryAsync(dirname(toPath));\n await rename(fromPath, toPath);\n await this.purgeImageVariants(fromPath);\n\n const hash = await this.hashFile(toPath);\n const stats = await stat(toPath);\n\n return {\n path: this.applyPrefix(to),\n url: this.url(to),\n size: stats.size,\n hash,\n mimeType: this.guessMimeType(to),\n driver: this.name,\n };\n }\n\n /**\n * List files in a directory\n */\n public async list(directory: string, options?: ListOptions): Promise<StorageFileInfo[]> {\n const absolutePath = this.getAbsolutePath(directory);\n const files: StorageFileInfo[] = [];\n\n // A listing target is a DIRECTORY, so guard with `directoryExistsAsync`.\n // `fileExistsAsync` resolves `false` for a folder, which would make `list`\n // always return [] for a real, populated directory.\n if (!(await directoryExistsAsync(absolutePath))) {\n return files;\n }\n\n const entries = await readdir(absolutePath, { withFileTypes: true });\n\n for (const entry of entries) {\n const entryPath = join(directory, entry.name);\n const entryStats = await stat(this.getAbsolutePath(entryPath));\n\n files.push({\n path: entryPath,\n name: entry.name,\n size: entryStats.size,\n isDirectory: entry.isDirectory(),\n lastModified: entryStats.mtime,\n mimeType: entry.isFile() ? this.guessMimeType(entry.name) : undefined,\n });\n\n // Recursively list subdirectories if requested\n if (options?.recursive && entry.isDirectory()) {\n const subFiles = await this.list(entryPath, options);\n files.push(...subFiles);\n }\n\n // Respect limit\n if (options?.limit && files.length >= options.limit) {\n break;\n }\n }\n\n return files;\n }\n\n // ============================================================\n // Path Operations\n // ============================================================\n\n /**\n * Get absolute filesystem path for a location\n */\n public path(location: string): string {\n return this.getAbsolutePath(location);\n }\n\n /**\n * Get the storage root directory\n */\n public getRoot(): string {\n return this.root;\n }\n\n // ============================================================\n // Utilities\n // ============================================================\n\n /**\n * Remove the cached image derivatives of a file that was just deleted or\n * moved away. Best effort: the file operation has already succeeded, so a\n * cache that cannot be cleared is logged, never thrown.\n */\n protected async purgeImageVariants(absolutePath: string): Promise<void> {\n try {\n await purgeImageVariantsOfFile(this.root, absolutePath);\n } catch (error) {\n log.warn(\n \"storage.local\",\n \"purge-image-variants\",\n `Could not remove cached image variants: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n }\n\n /**\n * Get absolute file path\n *\n * Routes through {@link resolveWithinRoot} so a location can never escape\n * the configured storage root via `..` traversal, an absolute path, or a\n * prefix breakout.\n */\n protected getAbsolutePath(location: string): string {\n const prefixedLocation = this.applyPrefix(location);\n const resolved = resolveWithinRoot(this.root, prefixedLocation);\n\n // The prefix is a containment boundary too: \"../t2/x\" under prefix \"t1\"\n // must not land in a sibling tenant's directory.\n const prefix = storageDriverContext.getPrefix() || this.options.prefix;\n\n if (prefix) {\n const prefixRoot = resolveWithinRoot(this.root, prefix.replace(/^[\\\\/]+|[\\\\/]+$/g, \"\"));\n resolveWithinRoot(prefixRoot, resolved);\n }\n\n return resolved;\n }\n\n /**\n * Convert various input types to Buffer\n */\n protected async toBuffer(file: Buffer | string | UploadedFile): Promise<Buffer> {\n if (Buffer.isBuffer(file)) {\n return file;\n }\n\n // A string is always content, never a source path\n if (typeof file === \"string\") {\n return Buffer.from(file);\n }\n\n return file.buffer();\n }\n\n /**\n * Calculate SHA-256 hash\n */\n protected calculateHash(buffer: Buffer): string {\n return crypto.createHash(\"sha256\").update(new Uint8Array(buffer)).digest(\"hex\");\n }\n\n /**\n * Calculate SHA-256 hash of a file by streaming it (constant memory)\n */\n protected async hashFile(absolutePath: string): Promise<string> {\n const hasher = crypto.createHash(\"sha256\");\n\n for await (const chunk of createReadStream(absolutePath)) {\n hasher.update(chunk);\n }\n\n return hasher.digest(\"hex\");\n }\n\n /**\n * Guess MIME type from file extension\n */\n protected guessMimeType(location: string): string {\n return getMimeType(location);\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { R2StorageDriverOptions } from "../types.mjs";
|
|
2
2
|
import { CloudDriver } from "./cloud-driver.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../../packages/core/src/storage/drivers/r2-driver.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Cloudflare R2 Storage Driver
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"r2-driver.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"r2-driver.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/r2-driver.ts"],"mappings":";;;;;;AA0BA;;;;;;;;;;;AAwB6B;;;;;;;;;cAxBhB,QAAA,SAAiB,WAAW,CAAC,sBAAA;;;;WAIxB,IAAA;;;;;;YAON,WAAA;;;;;;;;;;EAaH,GAAA,CAAI,QAAA;AAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"r2-driver.mjs","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"r2-driver.mjs","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/r2-driver.ts"],"sourcesContent":["import { ltrim } from \"@mongez/reinforcements\";\nimport type { R2StorageDriverOptions } from \"../types\";\nimport { CloudDriver } from \"./cloud-driver\";\n\n/**\n * Cloudflare R2 Storage Driver\n *\n * R2 is S3-compatible but uses a different URL structure and doesn't require regions.\n *\n * URL Patterns:\n * - With publicDomain: https://{publicDomain}/{key}\n * - With urlPrefix: {urlPrefix}/{key}\n * - Default public bucket: https://pub-{accountId}.r2.dev/{key}\n *\n * @example\n * ```typescript\n * const driver = new R2Driver({\n * bucket: \"my-bucket\",\n * region: \"auto\", // R2 doesn't use traditional regions\n * accessKeyId: process.env.R2_ACCESS_KEY_ID,\n * secretAccessKey: process.env.R2_SECRET_ACCESS_KEY,\n * accountId: process.env.R2_ACCOUNT_ID,\n * publicDomain: \"assets.example.com\", // Optional custom domain\n * });\n * ```\n */\nexport class R2Driver extends CloudDriver<R2StorageDriverOptions> {\n /**\n * Driver name\n */\n public readonly name = \"r2\";\n\n /**\n * Get R2 endpoint URL\n *\n * R2 endpoint format: https://{accountId}.r2.cloudflarestorage.com\n */\n protected getEndpoint(): string {\n return this.options.endpoint || `https://${this.options.accountId}.r2.cloudflarestorage.com`;\n }\n\n /**\n * Get public URL for file\n *\n * Priority: urlPrefix > publicDomain > default R2 URL\n *\n * Note: For R2 public access, you typically need to:\n * - Enable public access on the bucket\n * - Or use a custom domain through Cloudflare\n */\n public url(location: string): string {\n // 1. Use urlPrefix if configured — return it directly so the\n // publicDomain / default-host URLs below are NOT appended (which would\n // yield a double-host URL).\n if (this.options.urlPrefix) {\n const prefix = this.options.urlPrefix.replace(/\\/+$/, \"\");\n return `${prefix}/${ltrim(location, \"/\")}`;\n }\n\n // 2. Use publicDomain if configured\n if (this.options.publicDomain) {\n const domain = this.options.publicDomain.replace(/\\/+$/, \"\");\n return `${domain}/${location}`;\n }\n\n // 3. Fallback to R2 public bucket URL\n // Note: Public access must be enabled on the bucket for this to work\n return `https://pub-${this.options.accountId}.r2.dev/${location}`;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA0BA,IAAa,WAAb,cAA8B,YAAoC;;;cAIzC;;;;;;;CAOvB,AAAU,cAAsB;EAC9B,OAAO,KAAK,QAAQ,YAAY,WAAW,KAAK,QAAQ,UAAU;CACpE;;;;;;;;;;CAWA,AAAO,IAAI,UAA0B;EAInC,IAAI,KAAK,QAAQ,WAEf,OAAO,GADQ,KAAK,QAAQ,UAAU,QAAQ,QAAQ,EACvC,EAAE,GAAG,MAAM,UAAU,GAAG;EAIzC,IAAI,KAAK,QAAQ,cAEf,OAAO,GADQ,KAAK,QAAQ,aAAa,QAAQ,QAAQ,EAC1C,EAAE,GAAG;EAKtB,OAAO,eAAe,KAAK,QAAQ,UAAU,UAAU;CACzD;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { CloudStorageDriverOptions } from "../types.mjs";
|
|
2
2
|
import { CloudDriver } from "./cloud-driver.mjs";
|
|
3
3
|
|
|
4
|
-
//#region
|
|
4
|
+
//#region ../../packages/core/src/storage/drivers/s3-driver.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* AWS S3 Storage Driver
|
|
7
7
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"s3-driver.d.mts","names":[],"sources":["
|
|
1
|
+
{"version":3,"file":"s3-driver.d.mts","names":[],"sources":["../../../../../../../../../packages/core/src/storage/drivers/s3-driver.ts"],"mappings":";;;;;;AAmBA;;;;;;;;;;AAa6B;;;cAbhB,QAAA,SAAiB,WAAW,CAAC,yBAAA;;;;WAIxB,IAAA;;;;;;;;EAST,GAAA,CAAI,QAAA;AAAA"}
|