@jini-ai/cms 0.1.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/LICENSE +201 -0
- package/README.md +84 -0
- package/dist/content-types/agent-tools.d.ts +65 -0
- package/dist/content-types/agent-tools.d.ts.map +1 -0
- package/dist/content-types/agent-tools.js +172 -0
- package/dist/content-types/agent-tools.js.map +1 -0
- package/dist/content-types/cleanup.d.ts +118 -0
- package/dist/content-types/cleanup.d.ts.map +1 -0
- package/dist/content-types/cleanup.js +65 -0
- package/dist/content-types/cleanup.js.map +1 -0
- package/dist/content-types/errors.d.ts +90 -0
- package/dist/content-types/errors.d.ts.map +1 -0
- package/dist/content-types/errors.js +119 -0
- package/dist/content-types/errors.js.map +1 -0
- package/dist/content-types/field-defs.d.ts +25 -0
- package/dist/content-types/field-defs.d.ts.map +1 -0
- package/dist/content-types/field-defs.js +155 -0
- package/dist/content-types/field-defs.js.map +1 -0
- package/dist/content-types/index-provisioning.d.ts +94 -0
- package/dist/content-types/index-provisioning.d.ts.map +1 -0
- package/dist/content-types/index-provisioning.js +133 -0
- package/dist/content-types/index-provisioning.js.map +1 -0
- package/dist/content-types/index.d.ts +63 -0
- package/dist/content-types/index.d.ts.map +1 -0
- package/dist/content-types/index.js +36 -0
- package/dist/content-types/index.js.map +1 -0
- package/dist/content-types/lifecycle-dispatch.d.ts +38 -0
- package/dist/content-types/lifecycle-dispatch.d.ts.map +1 -0
- package/dist/content-types/lifecycle-dispatch.js +28 -0
- package/dist/content-types/lifecycle-dispatch.js.map +1 -0
- package/dist/content-types/lifecycle.d.ts +104 -0
- package/dist/content-types/lifecycle.d.ts.map +1 -0
- package/dist/content-types/lifecycle.js +143 -0
- package/dist/content-types/lifecycle.js.map +1 -0
- package/dist/content-types/list.d.ts +44 -0
- package/dist/content-types/list.d.ts.map +1 -0
- package/dist/content-types/list.js +13 -0
- package/dist/content-types/list.js.map +1 -0
- package/dist/content-types/repo.memory.d.ts +72 -0
- package/dist/content-types/repo.memory.d.ts.map +1 -0
- package/dist/content-types/repo.memory.js +71 -0
- package/dist/content-types/repo.memory.js.map +1 -0
- package/dist/content-types/tool-registrations.d.ts +65 -0
- package/dist/content-types/tool-registrations.d.ts.map +1 -0
- package/dist/content-types/tool-registrations.js +180 -0
- package/dist/content-types/tool-registrations.js.map +1 -0
- package/dist/content-types/types.d.ts +78 -0
- package/dist/content-types/types.d.ts.map +1 -0
- package/dist/content-types/types.js +32 -0
- package/dist/content-types/types.js.map +1 -0
- package/dist/content-types/write-service.d.ts +141 -0
- package/dist/content-types/write-service.d.ts.map +1 -0
- package/dist/content-types/write-service.js +180 -0
- package/dist/content-types/write-service.js.map +1 -0
- package/dist/core/commands/change-set.d.ts +98 -0
- package/dist/core/commands/change-set.d.ts.map +1 -0
- package/dist/core/commands/change-set.js +2 -0
- package/dist/core/commands/change-set.js.map +1 -0
- package/dist/core/commands/command.d.ts +168 -0
- package/dist/core/commands/command.d.ts.map +1 -0
- package/dist/core/commands/command.js +173 -0
- package/dist/core/commands/command.js.map +1 -0
- package/dist/core/index.d.ts +45 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +43 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/ports.d.ts +139 -0
- package/dist/core/ports.d.ts.map +1 -0
- package/dist/core/ports.js +2 -0
- package/dist/core/ports.js.map +1 -0
- package/dist/core/tools/registration-kit.d.ts +308 -0
- package/dist/core/tools/registration-kit.d.ts.map +1 -0
- package/dist/core/tools/registration-kit.js +381 -0
- package/dist/core/tools/registration-kit.js.map +1 -0
- package/dist/entries/agent-tools.d.ts +78 -0
- package/dist/entries/agent-tools.d.ts.map +1 -0
- package/dist/entries/agent-tools.js +158 -0
- package/dist/entries/agent-tools.js.map +1 -0
- package/dist/entries/errors.d.ts +43 -0
- package/dist/entries/errors.d.ts.map +1 -0
- package/dist/entries/errors.js +59 -0
- package/dist/entries/errors.js.map +1 -0
- package/dist/entries/field-validation.d.ts +70 -0
- package/dist/entries/field-validation.d.ts.map +1 -0
- package/dist/entries/field-validation.js +87 -0
- package/dist/entries/field-validation.js.map +1 -0
- package/dist/entries/index.d.ts +55 -0
- package/dist/entries/index.d.ts.map +1 -0
- package/dist/entries/index.js +38 -0
- package/dist/entries/index.js.map +1 -0
- package/dist/entries/lifecycle-dispatch.d.ts +15 -0
- package/dist/entries/lifecycle-dispatch.d.ts.map +1 -0
- package/dist/entries/lifecycle-dispatch.js +16 -0
- package/dist/entries/lifecycle-dispatch.js.map +1 -0
- package/dist/entries/list.d.ts +47 -0
- package/dist/entries/list.d.ts.map +1 -0
- package/dist/entries/list.js +12 -0
- package/dist/entries/list.js.map +1 -0
- package/dist/entries/repo.memory.d.ts +64 -0
- package/dist/entries/repo.memory.d.ts.map +1 -0
- package/dist/entries/repo.memory.js +73 -0
- package/dist/entries/repo.memory.js.map +1 -0
- package/dist/entries/tool-registrations.d.ts +52 -0
- package/dist/entries/tool-registrations.d.ts.map +1 -0
- package/dist/entries/tool-registrations.js +141 -0
- package/dist/entries/tool-registrations.js.map +1 -0
- package/dist/entries/types.d.ts +55 -0
- package/dist/entries/types.d.ts.map +1 -0
- package/dist/entries/types.js +2 -0
- package/dist/entries/types.js.map +1 -0
- package/dist/entries/write-service.d.ts +202 -0
- package/dist/entries/write-service.d.ts.map +1 -0
- package/dist/entries/write-service.js +204 -0
- package/dist/entries/write-service.js.map +1 -0
- package/dist/identity/admin-crud-service.d.ts +252 -0
- package/dist/identity/admin-crud-service.d.ts.map +1 -0
- package/dist/identity/admin-crud-service.js +437 -0
- package/dist/identity/admin-crud-service.js.map +1 -0
- package/dist/identity/agent-tool-input.d.ts +58 -0
- package/dist/identity/agent-tool-input.d.ts.map +1 -0
- package/dist/identity/agent-tool-input.js +126 -0
- package/dist/identity/agent-tool-input.js.map +1 -0
- package/dist/identity/agent-tools.d.ts +101 -0
- package/dist/identity/agent-tools.d.ts.map +1 -0
- package/dist/identity/agent-tools.js +290 -0
- package/dist/identity/agent-tools.js.map +1 -0
- package/dist/identity/auth-service.d.ts +87 -0
- package/dist/identity/auth-service.d.ts.map +1 -0
- package/dist/identity/auth-service.js +141 -0
- package/dist/identity/auth-service.js.map +1 -0
- package/dist/identity/authorize.d.ts +90 -0
- package/dist/identity/authorize.d.ts.map +1 -0
- package/dist/identity/authorize.js +94 -0
- package/dist/identity/authorize.js.map +1 -0
- package/dist/identity/grant-service.d.ts +198 -0
- package/dist/identity/grant-service.d.ts.map +1 -0
- package/dist/identity/grant-service.js +361 -0
- package/dist/identity/grant-service.js.map +1 -0
- package/dist/identity/hasher.d.ts +39 -0
- package/dist/identity/hasher.d.ts.map +1 -0
- package/dist/identity/hasher.js +39 -0
- package/dist/identity/hasher.js.map +1 -0
- package/dist/identity/index.d.ts +59 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +51 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/identity/password-policy.d.ts +58 -0
- package/dist/identity/password-policy.d.ts.map +1 -0
- package/dist/identity/password-policy.js +67 -0
- package/dist/identity/password-policy.js.map +1 -0
- package/dist/identity/permission-migrations.d.ts +86 -0
- package/dist/identity/permission-migrations.d.ts.map +1 -0
- package/dist/identity/permission-migrations.js +67 -0
- package/dist/identity/permission-migrations.js.map +1 -0
- package/dist/identity/permissions.d.ts +35 -0
- package/dist/identity/permissions.d.ts.map +1 -0
- package/dist/identity/permissions.js +603 -0
- package/dist/identity/permissions.js.map +1 -0
- package/dist/identity/ports.d.ts +201 -0
- package/dist/identity/ports.d.ts.map +1 -0
- package/dist/identity/ports.js +2 -0
- package/dist/identity/ports.js.map +1 -0
- package/dist/identity/repo.memory.d.ts +164 -0
- package/dist/identity/repo.memory.d.ts.map +1 -0
- package/dist/identity/repo.memory.js +224 -0
- package/dist/identity/repo.memory.js.map +1 -0
- package/dist/identity/seed.d.ts +42 -0
- package/dist/identity/seed.d.ts.map +1 -0
- package/dist/identity/seed.js +277 -0
- package/dist/identity/seed.js.map +1 -0
- package/dist/identity/tool-registrations.d.ts +50 -0
- package/dist/identity/tool-registrations.d.ts.map +1 -0
- package/dist/identity/tool-registrations.js +419 -0
- package/dist/identity/tool-registrations.js.map +1 -0
- package/dist/identity/types.d.ts +185 -0
- package/dist/identity/types.d.ts.map +1 -0
- package/dist/identity/types.js +64 -0
- package/dist/identity/types.js.map +1 -0
- package/dist/identity/username.d.ts +12 -0
- package/dist/identity/username.d.ts.map +1 -0
- package/dist/identity/username.js +14 -0
- package/dist/identity/username.js.map +1 -0
- package/dist/media/agent-tools.d.ts +66 -0
- package/dist/media/agent-tools.d.ts.map +1 -0
- package/dist/media/agent-tools.js +131 -0
- package/dist/media/agent-tools.js.map +1 -0
- package/dist/media/blob-gc-lock.d.ts +37 -0
- package/dist/media/blob-gc-lock.d.ts.map +1 -0
- package/dist/media/blob-gc-lock.js +55 -0
- package/dist/media/blob-gc-lock.js.map +1 -0
- package/dist/media/blob-gc.d.ts +246 -0
- package/dist/media/blob-gc.d.ts.map +1 -0
- package/dist/media/blob-gc.js +254 -0
- package/dist/media/blob-gc.js.map +1 -0
- package/dist/media/blob-key.d.ts +28 -0
- package/dist/media/blob-key.d.ts.map +1 -0
- package/dist/media/blob-key.js +11 -0
- package/dist/media/blob-key.js.map +1 -0
- package/dist/media/blob-store.fs.d.ts +23 -0
- package/dist/media/blob-store.fs.d.ts.map +1 -0
- package/dist/media/blob-store.fs.js +48 -0
- package/dist/media/blob-store.fs.js.map +1 -0
- package/dist/media/blob-store.memory.d.ts +22 -0
- package/dist/media/blob-store.memory.d.ts.map +1 -0
- package/dist/media/blob-store.memory.js +23 -0
- package/dist/media/blob-store.memory.js.map +1 -0
- package/dist/media/content-type-sniffer.d.ts +49 -0
- package/dist/media/content-type-sniffer.d.ts.map +1 -0
- package/dist/media/content-type-sniffer.js +141 -0
- package/dist/media/content-type-sniffer.js.map +1 -0
- package/dist/media/image-transformer.d.ts +45 -0
- package/dist/media/image-transformer.d.ts.map +1 -0
- package/dist/media/image-transformer.js +23 -0
- package/dist/media/image-transformer.js.map +1 -0
- package/dist/media/image-transformer.sharp.d.ts +26 -0
- package/dist/media/image-transformer.sharp.d.ts.map +1 -0
- package/dist/media/image-transformer.sharp.js +91 -0
- package/dist/media/image-transformer.sharp.js.map +1 -0
- package/dist/media/index.d.ts +43 -0
- package/dist/media/index.d.ts.map +1 -0
- package/dist/media/index.js +31 -0
- package/dist/media/index.js.map +1 -0
- package/dist/media/media-service.d.ts +244 -0
- package/dist/media/media-service.d.ts.map +1 -0
- package/dist/media/media-service.js +345 -0
- package/dist/media/media-service.js.map +1 -0
- package/dist/media/ports.d.ts +142 -0
- package/dist/media/ports.d.ts.map +1 -0
- package/dist/media/ports.js +2 -0
- package/dist/media/ports.js.map +1 -0
- package/dist/media/rendition-service.d.ts +66 -0
- package/dist/media/rendition-service.d.ts.map +1 -0
- package/dist/media/rendition-service.js +135 -0
- package/dist/media/rendition-service.js.map +1 -0
- package/dist/media/repo.memory.d.ts +107 -0
- package/dist/media/repo.memory.d.ts.map +1 -0
- package/dist/media/repo.memory.js +131 -0
- package/dist/media/repo.memory.js.map +1 -0
- package/dist/media/tool-registrations.d.ts +42 -0
- package/dist/media/tool-registrations.d.ts.map +1 -0
- package/dist/media/tool-registrations.js +121 -0
- package/dist/media/tool-registrations.js.map +1 -0
- package/dist/media/transform-lock.d.ts +36 -0
- package/dist/media/transform-lock.d.ts.map +1 -0
- package/dist/media/transform-lock.js +50 -0
- package/dist/media/transform-lock.js.map +1 -0
- package/dist/media/transform-registry.d.ts +103 -0
- package/dist/media/transform-registry.d.ts.map +1 -0
- package/dist/media/transform-registry.js +87 -0
- package/dist/media/transform-registry.js.map +1 -0
- package/dist/media/transform-types.d.ts +82 -0
- package/dist/media/transform-types.d.ts.map +1 -0
- package/dist/media/transform-types.js +47 -0
- package/dist/media/transform-types.js.map +1 -0
- package/dist/media/types.d.ts +150 -0
- package/dist/media/types.d.ts.map +1 -0
- package/dist/media/types.js +26 -0
- package/dist/media/types.js.map +1 -0
- package/dist/navigation/agent-tools.d.ts +90 -0
- package/dist/navigation/agent-tools.d.ts.map +1 -0
- package/dist/navigation/agent-tools.js +225 -0
- package/dist/navigation/agent-tools.js.map +1 -0
- package/dist/navigation/contracts.d.ts +98 -0
- package/dist/navigation/contracts.d.ts.map +1 -0
- package/dist/navigation/contracts.js +70 -0
- package/dist/navigation/contracts.js.map +1 -0
- package/dist/navigation/index.d.ts +39 -0
- package/dist/navigation/index.d.ts.map +1 -0
- package/dist/navigation/index.js +30 -0
- package/dist/navigation/index.js.map +1 -0
- package/dist/navigation/menu-service.d.ts +256 -0
- package/dist/navigation/menu-service.d.ts.map +1 -0
- package/dist/navigation/menu-service.js +382 -0
- package/dist/navigation/menu-service.js.map +1 -0
- package/dist/navigation/ports.d.ts +147 -0
- package/dist/navigation/ports.d.ts.map +1 -0
- package/dist/navigation/ports.js +2 -0
- package/dist/navigation/ports.js.map +1 -0
- package/dist/navigation/read-model.d.ts +11 -0
- package/dist/navigation/read-model.d.ts.map +1 -0
- package/dist/navigation/read-model.js +27 -0
- package/dist/navigation/read-model.js.map +1 -0
- package/dist/navigation/reconcile.d.ts +57 -0
- package/dist/navigation/reconcile.d.ts.map +1 -0
- package/dist/navigation/reconcile.js +33 -0
- package/dist/navigation/reconcile.js.map +1 -0
- package/dist/navigation/repo.memory.d.ts +137 -0
- package/dist/navigation/repo.memory.d.ts.map +1 -0
- package/dist/navigation/repo.memory.js +95 -0
- package/dist/navigation/repo.memory.js.map +1 -0
- package/dist/navigation/resolver.d.ts +110 -0
- package/dist/navigation/resolver.d.ts.map +1 -0
- package/dist/navigation/resolver.js +131 -0
- package/dist/navigation/resolver.js.map +1 -0
- package/dist/navigation/tool-registrations.d.ts +43 -0
- package/dist/navigation/tool-registrations.d.ts.map +1 -0
- package/dist/navigation/tool-registrations.js +126 -0
- package/dist/navigation/tool-registrations.js.map +1 -0
- package/dist/navigation/types.d.ts +207 -0
- package/dist/navigation/types.d.ts.map +1 -0
- package/dist/navigation/types.js +14 -0
- package/dist/navigation/types.js.map +1 -0
- package/dist/presentation/index.d.ts +15 -0
- package/dist/presentation/index.d.ts.map +1 -0
- package/dist/presentation/index.js +15 -0
- package/dist/presentation/index.js.map +1 -0
- package/dist/presentation/presentation.d.ts +72 -0
- package/dist/presentation/presentation.d.ts.map +1 -0
- package/dist/presentation/presentation.js +51 -0
- package/dist/presentation/presentation.js.map +1 -0
- package/dist/presentation/repo.memory.d.ts +9 -0
- package/dist/presentation/repo.memory.d.ts.map +1 -0
- package/dist/presentation/repo.memory.js +21 -0
- package/dist/presentation/repo.memory.js.map +1 -0
- package/dist/server/index.d.ts +28 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +28 -0
- package/dist/server/index.js.map +1 -0
- package/dist/settings/agent-tools.d.ts +83 -0
- package/dist/settings/agent-tools.d.ts.map +1 -0
- package/dist/settings/agent-tools.js +200 -0
- package/dist/settings/agent-tools.js.map +1 -0
- package/dist/settings/agent-writable-preferences.d.ts +67 -0
- package/dist/settings/agent-writable-preferences.d.ts.map +1 -0
- package/dist/settings/agent-writable-preferences.js +144 -0
- package/dist/settings/agent-writable-preferences.js.map +1 -0
- package/dist/settings/change-feed.d.ts +74 -0
- package/dist/settings/change-feed.d.ts.map +1 -0
- package/dist/settings/change-feed.js +61 -0
- package/dist/settings/change-feed.js.map +1 -0
- package/dist/settings/definitions-dispatch.d.ts +51 -0
- package/dist/settings/definitions-dispatch.d.ts.map +1 -0
- package/dist/settings/definitions-dispatch.js +86 -0
- package/dist/settings/definitions-dispatch.js.map +1 -0
- package/dist/settings/dictionaries/index.d.ts +45 -0
- package/dist/settings/dictionaries/index.d.ts.map +1 -0
- package/dist/settings/dictionaries/index.js +69 -0
- package/dist/settings/dictionaries/index.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ar.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ar.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ar.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ar.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.bn.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.bn.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.bn.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.bn.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.de.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.de.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.de.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.de.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.es.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.es.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.es.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.es.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fa.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.fa.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fa.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.fa.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fr.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.fr.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.fr.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.fr.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hi.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.hi.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hi.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.hi.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hu.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.hu.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.hu.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.hu.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.id.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.id.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.id.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.id.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.it.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.it.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.it.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.it.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ja.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ja.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ja.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ja.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ko.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ko.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ko.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ko.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pl.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.pl.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pl.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.pl.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.pt-BR.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ru.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ru.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ru.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ru.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.th.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.th.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.th.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.th.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.tr.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.tr.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.tr.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.tr.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.uk.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.uk.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.uk.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.uk.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ur.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.ur.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.ur.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.ur.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.zh-CN.js.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts +3 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.d.ts.map +1 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.js +28 -0
- package/dist/settings/dictionaries/settings-dialog.zh-TW.js.map +1 -0
- package/dist/settings/ensure-definitions.d.ts +88 -0
- package/dist/settings/ensure-definitions.d.ts.map +1 -0
- package/dist/settings/ensure-definitions.js +91 -0
- package/dist/settings/ensure-definitions.js.map +1 -0
- package/dist/settings/errors.d.ts +36 -0
- package/dist/settings/errors.d.ts.map +1 -0
- package/dist/settings/errors.js +40 -0
- package/dist/settings/errors.js.map +1 -0
- package/dist/settings/index.d.ts +37 -0
- package/dist/settings/index.d.ts.map +1 -0
- package/dist/settings/index.js +36 -0
- package/dist/settings/index.js.map +1 -0
- package/dist/settings/ports.d.ts +117 -0
- package/dist/settings/ports.d.ts.map +1 -0
- package/dist/settings/ports.js +2 -0
- package/dist/settings/ports.js.map +1 -0
- package/dist/settings/purge-service.d.ts +53 -0
- package/dist/settings/purge-service.d.ts.map +1 -0
- package/dist/settings/purge-service.js +105 -0
- package/dist/settings/purge-service.js.map +1 -0
- package/dist/settings/repo.memory.d.ts +119 -0
- package/dist/settings/repo.memory.d.ts.map +1 -0
- package/dist/settings/repo.memory.js +199 -0
- package/dist/settings/repo.memory.js.map +1 -0
- package/dist/settings/settings.d.ts +124 -0
- package/dist/settings/settings.d.ts.map +1 -0
- package/dist/settings/settings.js +238 -0
- package/dist/settings/settings.js.map +1 -0
- package/dist/settings/tool-registrations.d.ts +56 -0
- package/dist/settings/tool-registrations.d.ts.map +1 -0
- package/dist/settings/tool-registrations.js +240 -0
- package/dist/settings/tool-registrations.js.map +1 -0
- package/dist/settings/types.d.ts +125 -0
- package/dist/settings/types.d.ts.map +1 -0
- package/dist/settings/types.js +3 -0
- package/dist/settings/types.js.map +1 -0
- package/dist/settings/ui-tab-definitions.d.ts +41 -0
- package/dist/settings/ui-tab-definitions.d.ts.map +1 -0
- package/dist/settings/ui-tab-definitions.js +148 -0
- package/dist/settings/ui-tab-definitions.js.map +1 -0
- package/dist/settings/write-service.d.ts +314 -0
- package/dist/settings/write-service.d.ts.map +1 -0
- package/dist/settings/write-service.js +677 -0
- package/dist/settings/write-service.js.map +1 -0
- package/dist/taxonomy/agent-tools.d.ts +76 -0
- package/dist/taxonomy/agent-tools.d.ts.map +1 -0
- package/dist/taxonomy/agent-tools.js +178 -0
- package/dist/taxonomy/agent-tools.js.map +1 -0
- package/dist/taxonomy/content-lookup.d.ts +45 -0
- package/dist/taxonomy/content-lookup.d.ts.map +1 -0
- package/dist/taxonomy/content-lookup.js +9 -0
- package/dist/taxonomy/content-lookup.js.map +1 -0
- package/dist/taxonomy/index.d.ts +38 -0
- package/dist/taxonomy/index.d.ts.map +1 -0
- package/dist/taxonomy/index.js +38 -0
- package/dist/taxonomy/index.js.map +1 -0
- package/dist/taxonomy/list.d.ts +39 -0
- package/dist/taxonomy/list.d.ts.map +1 -0
- package/dist/taxonomy/list.js +19 -0
- package/dist/taxonomy/list.js.map +1 -0
- package/dist/taxonomy/merge-term.d.ts +94 -0
- package/dist/taxonomy/merge-term.d.ts.map +1 -0
- package/dist/taxonomy/merge-term.js +65 -0
- package/dist/taxonomy/merge-term.js.map +1 -0
- package/dist/taxonomy/repo.memory.d.ts +160 -0
- package/dist/taxonomy/repo.memory.d.ts.map +1 -0
- package/dist/taxonomy/repo.memory.js +171 -0
- package/dist/taxonomy/repo.memory.js.map +1 -0
- package/dist/taxonomy/validation-chain.d.ts +114 -0
- package/dist/taxonomy/validation-chain.d.ts.map +1 -0
- package/dist/taxonomy/validation-chain.js +152 -0
- package/dist/taxonomy/validation-chain.js.map +1 -0
- package/dist/taxonomy/write-service.d.ts +387 -0
- package/dist/taxonomy/write-service.d.ts.map +1 -0
- package/dist/taxonomy/write-service.js +350 -0
- package/dist/taxonomy/write-service.js.map +1 -0
- package/dist/workspace/agent-tools.d.ts +67 -0
- package/dist/workspace/agent-tools.d.ts.map +1 -0
- package/dist/workspace/agent-tools.js +103 -0
- package/dist/workspace/agent-tools.js.map +1 -0
- package/dist/workspace/create.d.ts +116 -0
- package/dist/workspace/create.d.ts.map +1 -0
- package/dist/workspace/create.js +69 -0
- package/dist/workspace/create.js.map +1 -0
- package/dist/workspace/delete.d.ts +50 -0
- package/dist/workspace/delete.d.ts.map +1 -0
- package/dist/workspace/delete.js +24 -0
- package/dist/workspace/delete.js.map +1 -0
- package/dist/workspace/index.d.ts +27 -0
- package/dist/workspace/index.d.ts.map +1 -0
- package/dist/workspace/index.js +27 -0
- package/dist/workspace/index.js.map +1 -0
- package/dist/workspace/repo.memory.d.ts +34 -0
- package/dist/workspace/repo.memory.d.ts.map +1 -0
- package/dist/workspace/repo.memory.js +50 -0
- package/dist/workspace/repo.memory.js.map +1 -0
- package/dist/workspace/tool-registrations.d.ts +38 -0
- package/dist/workspace/tool-registrations.d.ts.map +1 -0
- package/dist/workspace/tool-registrations.js +71 -0
- package/dist/workspace/tool-registrations.js.map +1 -0
- package/dist/workspace/update.d.ts +52 -0
- package/dist/workspace/update.d.ts.map +1 -0
- package/dist/workspace/update.js +41 -0
- package/dist/workspace/update.js.map +1 -0
- package/package.json +149 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file In-memory `BlobStorePort` test double (port/adapter rule-of-two, second
|
|
3
|
+
* adapter alongside `blob-store.fs.ts`). Used by hermetic tests and any
|
|
4
|
+
* host's default dev/test composition root.
|
|
5
|
+
*/
|
|
6
|
+
import type { BlobStorePort, PutBlobInput } from "./ports.js";
|
|
7
|
+
export declare class InMemoryBlobStore implements BlobStorePort {
|
|
8
|
+
private readonly bytesByKey;
|
|
9
|
+
put(input: PutBlobInput): Promise<{
|
|
10
|
+
storageKey: string;
|
|
11
|
+
}>;
|
|
12
|
+
get(input: {
|
|
13
|
+
storageKey: string;
|
|
14
|
+
}): Promise<Uint8Array>;
|
|
15
|
+
exists(input: {
|
|
16
|
+
storageKey: string;
|
|
17
|
+
}): Promise<boolean>;
|
|
18
|
+
remove(input: {
|
|
19
|
+
storageKey: string;
|
|
20
|
+
}): Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=blob-store.memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blob-store.memory.d.ts","sourceRoot":"","sources":["../../src/media/blob-store.memory.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG9D,qBAAa,iBAAkB,YAAW,aAAa;IACrD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAiC;IAEtD,GAAG,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,CAAC;IAMzD,GAAG,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC;IAQvD,MAAM,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvD,MAAM,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC;CAG3D"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { computeBlobStorageKey } from "./blob-key.js";
|
|
2
|
+
export class InMemoryBlobStore {
|
|
3
|
+
bytesByKey = new Map();
|
|
4
|
+
async put(input) {
|
|
5
|
+
const storageKey = computeBlobStorageKey(input);
|
|
6
|
+
this.bytesByKey.set(storageKey, input.bytes);
|
|
7
|
+
return { storageKey };
|
|
8
|
+
}
|
|
9
|
+
async get(input) {
|
|
10
|
+
const bytes = this.bytesByKey.get(input.storageKey);
|
|
11
|
+
if (!bytes) {
|
|
12
|
+
throw new Error(`blob '${input.storageKey}' was not found`);
|
|
13
|
+
}
|
|
14
|
+
return bytes;
|
|
15
|
+
}
|
|
16
|
+
async exists(input) {
|
|
17
|
+
return this.bytesByKey.has(input.storageKey);
|
|
18
|
+
}
|
|
19
|
+
async remove(input) {
|
|
20
|
+
this.bytesByKey.delete(input.storageKey);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=blob-store.memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"blob-store.memory.js","sourceRoot":"","sources":["../../src/media/blob-store.memory.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,MAAM,OAAO,iBAAiB;IACX,UAAU,GAAG,IAAI,GAAG,EAAsB,CAAC;IAE5D,KAAK,CAAC,GAAG,CAAC,KAAmB;QAC3B,MAAM,UAAU,GAAG,qBAAqB,CAAC,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,UAAU,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO,EAAE,UAAU,EAAE,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,KAA6B;QACrC,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QACpD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,KAAK,CAAC,SAAS,KAAK,CAAC,UAAU,iBAAiB,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAA6B;QACxC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,KAA6B;QACxC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC3C,CAAC;CACF"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Magic-byte content-type sniffer for media originals.
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* `uploadMedia` (`media-service.ts`) validates only a client-supplied `contentType`
|
|
6
|
+
* STRING against an advisory allowlist — it never inspects the actual bytes (see
|
|
7
|
+
* that file's header, point 4: "an attacker-controlled `contentType` header is
|
|
8
|
+
* trusted, which the real ingress policy would never do"). Neither `media` nor
|
|
9
|
+
* `asset_blobs` persists a real content type at all (no column exists). Any route
|
|
10
|
+
* that serves an asset's original bytes back out therefore cannot trust either the
|
|
11
|
+
* upload-time string or any stored column for `Content-Type` — it must derive the
|
|
12
|
+
* type itself, from the bytes it is about to send, every time it serves them. That
|
|
13
|
+
* is a host route's job, not this module's — this module only supplies the sniff.
|
|
14
|
+
*
|
|
15
|
+
* This is an ALLOWLIST sniffer, not a general-purpose one: {@link sniffContentType}
|
|
16
|
+
* recognizes exactly the binary signatures named below and returns
|
|
17
|
+
* `application/octet-stream` for anything else. The one deliberate exception is
|
|
18
|
+
* markup that looks like HTML or SVG — see {@link isHtmlLike}/{@link isSvgLike} —
|
|
19
|
+
* which this module DOES detect and label, specifically so a caller can single out
|
|
20
|
+
* "textual markup that is a same-origin stored-XSS vector if ever served as its own
|
|
21
|
+
* content type" from "an arbitrary unrecognized blob" and act on it explicitly
|
|
22
|
+
* (a serving route can force `Content-Disposition: attachment` for the former). This
|
|
23
|
+
* module does not attempt general-purpose HTML/XML sniffing beyond that.
|
|
24
|
+
*
|
|
25
|
+
* Detection windows: every binary signature check below only ever reads the first
|
|
26
|
+
* 12 bytes; the markup checks decode up to {@link TEXT_SNIFF_WINDOW} leading bytes
|
|
27
|
+
* (the same 512-byte order of magnitude the WHATWG MIME Sniffing Standard uses for
|
|
28
|
+
* its "read the first N bytes" unknown-type algorithms —
|
|
29
|
+
* https://mimesniff.spec.whatwg.org/#reading-the-resource-header — this module
|
|
30
|
+
* borrows only that window-size convention, not the spec's actual algorithm).
|
|
31
|
+
*/
|
|
32
|
+
/** Recognized outputs. Anything not covered here falls back to the network's
|
|
33
|
+
* default-safe unknown-binary label — see {@link sniffContentType}'s doc. */
|
|
34
|
+
export type SniffedContentType = "image/png" | "image/jpeg" | "image/gif" | "image/webp" | "video/mp4" | "video/webm" | "text/html" | "image/svg+xml" | "application/octet-stream";
|
|
35
|
+
/**
|
|
36
|
+
* Identifies a media type from `bytes`' leading magic bytes. Allowlist-shaped: only the formats
|
|
37
|
+
* named in {@link SniffedContentType} are ever returned as something other than
|
|
38
|
+
* `"application/octet-stream"` — an input this function does not recognize (including a truncated,
|
|
39
|
+
* corrupt, or genuinely unknown-format file) always falls back to the safe default, it never
|
|
40
|
+
* guesses. `text/html`/`image/svg+xml` are the one case this module positively looks for rather
|
|
41
|
+
* than falls back to, precisely so a caller can treat them as hostile rather than merely unknown
|
|
42
|
+
* (see file header).
|
|
43
|
+
*
|
|
44
|
+
* @complexity O(1) — every binary check reads at most 12 bytes; the textual checks decode at most
|
|
45
|
+
* {@link TEXT_SNIFF_WINDOW} bytes, a fixed constant independent of `bytes.length`.
|
|
46
|
+
* @overallScore 100
|
|
47
|
+
*/
|
|
48
|
+
export declare function sniffContentType(bytes: Uint8Array): SniffedContentType;
|
|
49
|
+
//# sourceMappingURL=content-type-sniffer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-type-sniffer.d.ts","sourceRoot":"","sources":["../../src/media/content-type-sniffer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;6EAC6E;AAC7E,MAAM,MAAM,kBAAkB,GAC1B,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,WAAW,GACX,YAAY,GACZ,WAAW,GACX,eAAe,GACf,0BAA0B,CAAC;AA2F/B;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,kBAAkB,CAatE"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Magic-byte content-type sniffer for media originals.
|
|
3
|
+
*
|
|
4
|
+
* Purpose:
|
|
5
|
+
* `uploadMedia` (`media-service.ts`) validates only a client-supplied `contentType`
|
|
6
|
+
* STRING against an advisory allowlist — it never inspects the actual bytes (see
|
|
7
|
+
* that file's header, point 4: "an attacker-controlled `contentType` header is
|
|
8
|
+
* trusted, which the real ingress policy would never do"). Neither `media` nor
|
|
9
|
+
* `asset_blobs` persists a real content type at all (no column exists). Any route
|
|
10
|
+
* that serves an asset's original bytes back out therefore cannot trust either the
|
|
11
|
+
* upload-time string or any stored column for `Content-Type` — it must derive the
|
|
12
|
+
* type itself, from the bytes it is about to send, every time it serves them. That
|
|
13
|
+
* is a host route's job, not this module's — this module only supplies the sniff.
|
|
14
|
+
*
|
|
15
|
+
* This is an ALLOWLIST sniffer, not a general-purpose one: {@link sniffContentType}
|
|
16
|
+
* recognizes exactly the binary signatures named below and returns
|
|
17
|
+
* `application/octet-stream` for anything else. The one deliberate exception is
|
|
18
|
+
* markup that looks like HTML or SVG — see {@link isHtmlLike}/{@link isSvgLike} —
|
|
19
|
+
* which this module DOES detect and label, specifically so a caller can single out
|
|
20
|
+
* "textual markup that is a same-origin stored-XSS vector if ever served as its own
|
|
21
|
+
* content type" from "an arbitrary unrecognized blob" and act on it explicitly
|
|
22
|
+
* (a serving route can force `Content-Disposition: attachment` for the former). This
|
|
23
|
+
* module does not attempt general-purpose HTML/XML sniffing beyond that.
|
|
24
|
+
*
|
|
25
|
+
* Detection windows: every binary signature check below only ever reads the first
|
|
26
|
+
* 12 bytes; the markup checks decode up to {@link TEXT_SNIFF_WINDOW} leading bytes
|
|
27
|
+
* (the same 512-byte order of magnitude the WHATWG MIME Sniffing Standard uses for
|
|
28
|
+
* its "read the first N bytes" unknown-type algorithms —
|
|
29
|
+
* https://mimesniff.spec.whatwg.org/#reading-the-resource-header — this module
|
|
30
|
+
* borrows only that window-size convention, not the spec's actual algorithm).
|
|
31
|
+
*/
|
|
32
|
+
/** Bounded leading window used only for the textual (HTML/SVG) checks — see file header. */
|
|
33
|
+
const TEXT_SNIFF_WINDOW = 512;
|
|
34
|
+
/** `true` iff `bytes` is long enough and holds `expected` starting at `offset`. Never throws on a
|
|
35
|
+
* short input — a too-short buffer simply fails the length check, matching every other predicate
|
|
36
|
+
* in this file's "no exceptions, just non-matches" contract. */
|
|
37
|
+
function bytesEqualAt(bytes, offset, expected) {
|
|
38
|
+
if (bytes.length < offset + expected.length)
|
|
39
|
+
return false;
|
|
40
|
+
for (let i = 0; i < expected.length; i++) {
|
|
41
|
+
if (bytes[offset + i] !== expected[i])
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
function asciiEqualAt(bytes, offset, expected) {
|
|
47
|
+
return bytesEqualAt(bytes, offset, Array.from(expected, (ch) => ch.charCodeAt(0)));
|
|
48
|
+
}
|
|
49
|
+
const PNG_SIGNATURE = [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a];
|
|
50
|
+
const JPEG_SIGNATURE = [0xff, 0xd8, 0xff];
|
|
51
|
+
/** EBML header — shared by the whole Matroska family (`.mkv`/`.webm`); this sniffer only ever
|
|
52
|
+
* labels it `video/webm` since WebM is the only Matroska-family format in this route's scope. */
|
|
53
|
+
const EBML_SIGNATURE = [0x1a, 0x45, 0xdf, 0xa3];
|
|
54
|
+
function isPng(bytes) {
|
|
55
|
+
return bytesEqualAt(bytes, 0, PNG_SIGNATURE);
|
|
56
|
+
}
|
|
57
|
+
function isJpeg(bytes) {
|
|
58
|
+
return bytesEqualAt(bytes, 0, JPEG_SIGNATURE);
|
|
59
|
+
}
|
|
60
|
+
function isGif(bytes) {
|
|
61
|
+
return asciiEqualAt(bytes, 0, "GIF87a") || asciiEqualAt(bytes, 0, "GIF89a");
|
|
62
|
+
}
|
|
63
|
+
/** RIFF container with a `WEBP` form type — bytes 4-7 are a chunk size (variable, not checked). */
|
|
64
|
+
function isWebp(bytes) {
|
|
65
|
+
return asciiEqualAt(bytes, 0, "RIFF") && asciiEqualAt(bytes, 8, "WEBP");
|
|
66
|
+
}
|
|
67
|
+
/** ISO-BMFF (MP4 and its siblings): a leading box whose 4-byte type tag at offset 4 is `ftyp`. The
|
|
68
|
+
* box's own size field (offset 0-3) is deliberately not checked — it varies by file. */
|
|
69
|
+
function isIsoBmffMp4(bytes) {
|
|
70
|
+
return asciiEqualAt(bytes, 4, "ftyp");
|
|
71
|
+
}
|
|
72
|
+
function isWebm(bytes) {
|
|
73
|
+
return bytesEqualAt(bytes, 0, EBML_SIGNATURE);
|
|
74
|
+
}
|
|
75
|
+
const UTF8_BOM = [0xef, 0xbb, 0xbf];
|
|
76
|
+
/** Decodes up to {@link TEXT_SNIFF_WINDOW} leading bytes as latin1 (byte-for-byte, never throws on
|
|
77
|
+
* invalid UTF-8 the way a strict "utf8" decode could), strips a leading UTF-8 BOM plus any leading
|
|
78
|
+
* ASCII whitespace, and lowercases — mirrors the "skip leading noise before sniffing markup" step
|
|
79
|
+
* browsers perform before matching tag prefixes. */
|
|
80
|
+
function leadingText(bytes) {
|
|
81
|
+
const window = bytes.subarray(0, Math.min(bytes.length, TEXT_SNIFF_WINDOW));
|
|
82
|
+
const decoded = Buffer.from(window).toString("latin1");
|
|
83
|
+
const withoutBom = bytesEqualAt(window, 0, UTF8_BOM) ? decoded.slice(UTF8_BOM.length) : decoded;
|
|
84
|
+
return withoutBom.replace(/^\s+/, "").toLowerCase();
|
|
85
|
+
}
|
|
86
|
+
const HTML_PREFIXES = ["<!doctype html", "<html", "<head", "<script", "<body", "<iframe", "<title", "<frameset"];
|
|
87
|
+
/** Matches a leading HTML tag prefix directly, or an XHTML document whose `<?xml ...?>` prolog is
|
|
88
|
+
* followed by `<html` within the sniffed window — either shape is `text/html`-equivalent for this
|
|
89
|
+
* module's purpose (a same-origin-render XSS vector), so both collapse to `"text/html"` rather than
|
|
90
|
+
* a separate `application/xhtml+xml` value (a serving route still blocks that literal string too, as
|
|
91
|
+
* defense in depth against a future caller adding it here). */
|
|
92
|
+
function isHtmlLike(text) {
|
|
93
|
+
if (HTML_PREFIXES.some((prefix) => text.startsWith(prefix)))
|
|
94
|
+
return true;
|
|
95
|
+
if (text.startsWith("<?xml"))
|
|
96
|
+
return text.includes("<html");
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
/** Matches a leading `<svg` root element, or an XML prolog followed by `<svg` within the sniffed
|
|
100
|
+
* window (`<?xml version="1.0"?><svg ...>`, the common real-world SVG file shape). */
|
|
101
|
+
function isSvgLike(text) {
|
|
102
|
+
if (text.startsWith("<svg"))
|
|
103
|
+
return true;
|
|
104
|
+
if (text.startsWith("<?xml"))
|
|
105
|
+
return text.includes("<svg");
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Identifies a media type from `bytes`' leading magic bytes. Allowlist-shaped: only the formats
|
|
110
|
+
* named in {@link SniffedContentType} are ever returned as something other than
|
|
111
|
+
* `"application/octet-stream"` — an input this function does not recognize (including a truncated,
|
|
112
|
+
* corrupt, or genuinely unknown-format file) always falls back to the safe default, it never
|
|
113
|
+
* guesses. `text/html`/`image/svg+xml` are the one case this module positively looks for rather
|
|
114
|
+
* than falls back to, precisely so a caller can treat them as hostile rather than merely unknown
|
|
115
|
+
* (see file header).
|
|
116
|
+
*
|
|
117
|
+
* @complexity O(1) — every binary check reads at most 12 bytes; the textual checks decode at most
|
|
118
|
+
* {@link TEXT_SNIFF_WINDOW} bytes, a fixed constant independent of `bytes.length`.
|
|
119
|
+
* @overallScore 100
|
|
120
|
+
*/
|
|
121
|
+
export function sniffContentType(bytes) {
|
|
122
|
+
if (isPng(bytes))
|
|
123
|
+
return "image/png";
|
|
124
|
+
if (isJpeg(bytes))
|
|
125
|
+
return "image/jpeg";
|
|
126
|
+
if (isGif(bytes))
|
|
127
|
+
return "image/gif";
|
|
128
|
+
if (isWebp(bytes))
|
|
129
|
+
return "image/webp";
|
|
130
|
+
if (isIsoBmffMp4(bytes))
|
|
131
|
+
return "video/mp4";
|
|
132
|
+
if (isWebm(bytes))
|
|
133
|
+
return "video/webm";
|
|
134
|
+
const text = leadingText(bytes);
|
|
135
|
+
if (isHtmlLike(text))
|
|
136
|
+
return "text/html";
|
|
137
|
+
if (isSvgLike(text))
|
|
138
|
+
return "image/svg+xml";
|
|
139
|
+
return "application/octet-stream";
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=content-type-sniffer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content-type-sniffer.js","sourceRoot":"","sources":["../../src/media/content-type-sniffer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file `ImageTransformerPort` (port/adapter rule-of-two) — the seam between
|
|
3
|
+
* rendition generation (`rendition-service.ts`) and the actual pixel
|
|
4
|
+
* operation. Two adapters:
|
|
5
|
+
* - `InMemoryImageTransformer` (this file) — deterministic test double, no
|
|
6
|
+
* real image codec. Default for hermetic tests and a dev/test composition
|
|
7
|
+
* root, mirroring `InMemoryBlobStore`'s role next to `LocalFsBlobStore`.
|
|
8
|
+
* - `SharpImageTransformer` (`image-transformer.sharp.ts`) — the real
|
|
9
|
+
* adapter, wired to call `sharp`. See that file's header: `sharp` is an
|
|
10
|
+
* optional runtime dependency, loaded lazily, not a hard import.
|
|
11
|
+
*/
|
|
12
|
+
import type { TransformParams } from "./transform-types.js";
|
|
13
|
+
export interface TransformImageInput {
|
|
14
|
+
bytes: Uint8Array;
|
|
15
|
+
params: TransformParams;
|
|
16
|
+
}
|
|
17
|
+
export interface TransformImageOutput {
|
|
18
|
+
bytes: Uint8Array;
|
|
19
|
+
contentType: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Runs one named transform's declared parameters against source bytes,
|
|
23
|
+
* producing re-encoded output bytes ("renditions are always
|
|
24
|
+
* re-encoded"). Implementations are expected to be pure with respect to
|
|
25
|
+
* `input` (same bytes + same params -> same output), which is what makes the
|
|
26
|
+
* content-addressed rendition storage key (`rendition-service.ts`) sound.
|
|
27
|
+
*/
|
|
28
|
+
export interface ImageTransformerPort {
|
|
29
|
+
transform(input: TransformImageInput): Promise<TransformImageOutput>;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Deterministic test double. NOT a real image codec — it does not resize or
|
|
33
|
+
* re-encode pixels. It prefixes the source bytes with a small tag describing
|
|
34
|
+
* the applied `params` so tests can assert that (a) different params yield
|
|
35
|
+
* different, reproducible output bytes and (b) the same params yield the
|
|
36
|
+
* same output bytes twice (idempotent, single-flight-safe). Production code
|
|
37
|
+
* must use `SharpImageTransformer` instead — see that file's header.
|
|
38
|
+
*
|
|
39
|
+
* @complexity O(n) in input byte length (one concat).
|
|
40
|
+
* @overallScore 100
|
|
41
|
+
*/
|
|
42
|
+
export declare class InMemoryImageTransformer implements ImageTransformerPort {
|
|
43
|
+
transform(input: TransformImageInput): Promise<TransformImageOutput>;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=image-transformer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-transformer.d.ts","sourceRoot":"","sources":["../../src/media/image-transformer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAG5D,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,UAAU,CAAC;IAClB,MAAM,EAAE,eAAe,CAAC;CACzB;AAED,MAAM,WAAW,oBAAoB;IACnC,KAAK,EAAE,UAAU,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAAC;CACtE;AAED;;;;;;;;;;GAUG;AACH,qBAAa,wBAAyB,YAAW,oBAAoB;IAC7D,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAQ3E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { mimeForTransformFormat } from "./transform-types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Deterministic test double. NOT a real image codec — it does not resize or
|
|
4
|
+
* re-encode pixels. It prefixes the source bytes with a small tag describing
|
|
5
|
+
* the applied `params` so tests can assert that (a) different params yield
|
|
6
|
+
* different, reproducible output bytes and (b) the same params yield the
|
|
7
|
+
* same output bytes twice (idempotent, single-flight-safe). Production code
|
|
8
|
+
* must use `SharpImageTransformer` instead — see that file's header.
|
|
9
|
+
*
|
|
10
|
+
* @complexity O(n) in input byte length (one concat).
|
|
11
|
+
* @overallScore 100
|
|
12
|
+
*/
|
|
13
|
+
export class InMemoryImageTransformer {
|
|
14
|
+
async transform(input) {
|
|
15
|
+
const tag = `TEST_TRANSFORM:${JSON.stringify(input.params)}:`;
|
|
16
|
+
const tagBytes = new TextEncoder().encode(tag);
|
|
17
|
+
const output = new Uint8Array(tagBytes.length + input.bytes.length);
|
|
18
|
+
output.set(tagBytes, 0);
|
|
19
|
+
output.set(input.bytes, tagBytes.length);
|
|
20
|
+
return { bytes: output, contentType: mimeForTransformFormat(input.params.format) };
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=image-transformer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-transformer.js","sourceRoot":"","sources":["../../src/media/image-transformer.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAuB9D;;;;;;;;;;GAUG;AACH,MAAM,OAAO,wBAAwB;IACnC,KAAK,CAAC,SAAS,CAAC,KAA0B;QACxC,MAAM,GAAG,GAAG,kBAAkB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;QAC9D,MAAM,QAAQ,GAAG,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QACxB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;IACrF,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ImageTransformerPort, TransformImageInput, TransformImageOutput } from "./image-transformer.js";
|
|
2
|
+
/** Thrown by {@link SharpImageTransformer.transform} when the `sharp` package cannot be loaded. */
|
|
3
|
+
export declare class ImageTransformUnavailableError extends Error {
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* Real `ImageTransformerPort` adapter. Applies `params.width`/`height`
|
|
7
|
+
* (via `sharp().resize(...)`, only when at least one is set) then
|
|
8
|
+
* `params.format` (via `sharp().toFormat(...)`, always — re-encode is
|
|
9
|
+
* unconditional).
|
|
10
|
+
*
|
|
11
|
+
* @complexity O(pixels) — dominated by `sharp`'s native resize/encode work,
|
|
12
|
+
* outside this function's control. Runs IN-PROCESS in this build (the
|
|
13
|
+
* out-of-process worker the original design calls for to protect the host from
|
|
14
|
+
* `sharp` OOMing is explicitly out of scope for this task — see
|
|
15
|
+
* `rendition-service.ts`'s file header).
|
|
16
|
+
* @overallScore 90
|
|
17
|
+
* @findings Medium: untested against real `sharp` output unless the
|
|
18
|
+
* consuming build actually has `sharp` installed — only the failure path
|
|
19
|
+
* (`ImageTransformUnavailableError`) is guaranteed reachable otherwise. The
|
|
20
|
+
* success-path code is reviewed for correctness against `sharp`'s documented
|
|
21
|
+
* API.
|
|
22
|
+
*/
|
|
23
|
+
export declare class SharpImageTransformer implements ImageTransformerPort {
|
|
24
|
+
transform(input: TransformImageInput): Promise<TransformImageOutput>;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=image-transformer.sharp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-transformer.sharp.d.ts","sourceRoot":"","sources":["../../src/media/image-transformer.sharp.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAK9G,mGAAmG;AACnG,qBAAa,8BAA+B,SAAQ,KAAK;CAAG;AAoC5D;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,qBAAsB,YAAW,oBAAoB;IAC1D,SAAS,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;CAkB3E"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Real `ImageTransformerPort` adapter — calls `sharp` to actually
|
|
3
|
+
* resize/re-encode pixels (renditions are always re-encoded,
|
|
4
|
+
* never passed through unmodified).
|
|
5
|
+
*
|
|
6
|
+
* `sharp` is an OPTIONAL runtime dependency of this package (mirrors
|
|
7
|
+
* `identity/hasher.ts`'s treatment of `argon2`), not a hard one — a host that
|
|
8
|
+
* only wants `InMemoryImageTransformer` (tests, or a build that has no need
|
|
9
|
+
* for real pixel transforms) must not be forced to install a native binary
|
|
10
|
+
* just by importing `./media`. Two consequences follow:
|
|
11
|
+
*
|
|
12
|
+
* 1. `sharp` is loaded via `node:module`'s `createRequire`, not a static
|
|
13
|
+
* `import`/`require` of the string `"sharp"` — this is what lets the
|
|
14
|
+
* module resolve and typecheck even in an environment/build where `sharp`
|
|
15
|
+
* is not installed at all. Nothing in this package's own `tsconfig.json`
|
|
16
|
+
* needs `sharp`'s types as a result: the narrow `SharpFactory`/
|
|
17
|
+
* `SharpInstance` shapes below are hand-declared and the loaded value is
|
|
18
|
+
* cast to them, exactly the same "not statically type-checked against the
|
|
19
|
+
* real package" contract the original of this adapter always had.
|
|
20
|
+
* 2. The load is deferred to the moment a transform actually needs to run,
|
|
21
|
+
* not to module-evaluation time. This file is reachable from a host's
|
|
22
|
+
* request-serving import graph (wired into its route deps for the real
|
|
23
|
+
* running server), so a top-level import would throw `MODULE_NOT_FOUND`
|
|
24
|
+
* on every boot, for every request, even ones that never touch a
|
|
25
|
+
* transform, if `sharp` were ever absent. The lazy load scopes that
|
|
26
|
+
* failure mode to the one call site that needs it, surfaced as
|
|
27
|
+
* {@link ImageTransformUnavailableError} — a named, thrown error, not a
|
|
28
|
+
* silently-passed-through/faked image.
|
|
29
|
+
*/
|
|
30
|
+
import { createRequire } from "node:module";
|
|
31
|
+
import { mimeForTransformFormat } from "./transform-types.js";
|
|
32
|
+
const require = createRequire(import.meta.url);
|
|
33
|
+
/** Thrown by {@link SharpImageTransformer.transform} when the `sharp` package cannot be loaded. */
|
|
34
|
+
export class ImageTransformUnavailableError extends Error {
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Lazily resolves the `sharp` module. See file header for why this is a
|
|
38
|
+
* deferred, untyped `require()` (via `createRequire`) rather than a
|
|
39
|
+
* top-level `import`.
|
|
40
|
+
*
|
|
41
|
+
* @complexity O(1) — a single `require` call, cached by Node's module system
|
|
42
|
+
* on subsequent calls.
|
|
43
|
+
* @overallScore 100
|
|
44
|
+
*/
|
|
45
|
+
function loadSharpFactory() {
|
|
46
|
+
try {
|
|
47
|
+
return require("sharp");
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
throw new ImageTransformUnavailableError("the 'sharp' npm package is not installed in this environment (run `npm install sharp`) — " +
|
|
51
|
+
"SharpImageTransformer cannot perform a real pixel transform without it. This is a " +
|
|
52
|
+
"disclosed, optional-dependency blocker, not a silent stub: no bytes are faked or passed " +
|
|
53
|
+
"through unmodified.");
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Real `ImageTransformerPort` adapter. Applies `params.width`/`height`
|
|
58
|
+
* (via `sharp().resize(...)`, only when at least one is set) then
|
|
59
|
+
* `params.format` (via `sharp().toFormat(...)`, always — re-encode is
|
|
60
|
+
* unconditional).
|
|
61
|
+
*
|
|
62
|
+
* @complexity O(pixels) — dominated by `sharp`'s native resize/encode work,
|
|
63
|
+
* outside this function's control. Runs IN-PROCESS in this build (the
|
|
64
|
+
* out-of-process worker the original design calls for to protect the host from
|
|
65
|
+
* `sharp` OOMing is explicitly out of scope for this task — see
|
|
66
|
+
* `rendition-service.ts`'s file header).
|
|
67
|
+
* @overallScore 90
|
|
68
|
+
* @findings Medium: untested against real `sharp` output unless the
|
|
69
|
+
* consuming build actually has `sharp` installed — only the failure path
|
|
70
|
+
* (`ImageTransformUnavailableError`) is guaranteed reachable otherwise. The
|
|
71
|
+
* success-path code is reviewed for correctness against `sharp`'s documented
|
|
72
|
+
* API.
|
|
73
|
+
*/
|
|
74
|
+
export class SharpImageTransformer {
|
|
75
|
+
async transform(input) {
|
|
76
|
+
const sharpFactory = loadSharpFactory();
|
|
77
|
+
let pipeline = sharpFactory(Buffer.from(input.bytes));
|
|
78
|
+
if (input.params.width !== undefined || input.params.height !== undefined) {
|
|
79
|
+
pipeline = pipeline.resize(input.params.width, input.params.height, {
|
|
80
|
+
fit: input.params.fit ?? "cover",
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
pipeline = pipeline.toFormat(input.params.format);
|
|
84
|
+
const outBuffer = await pipeline.toBuffer();
|
|
85
|
+
return {
|
|
86
|
+
bytes: new Uint8Array(outBuffer),
|
|
87
|
+
contentType: mimeForTransformFormat(input.params.format),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=image-transformer.sharp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-transformer.sharp.js","sourceRoot":"","sources":["../../src/media/image-transformer.sharp.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC;AAE9D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,mGAAmG;AACnG,MAAM,OAAO,8BAA+B,SAAQ,KAAK;CAAG;AAc5D;;;;;;;;GAQG;AACH,SAAS,gBAAgB;IACvB,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,OAAO,CAAiB,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,8BAA8B,CACtC,2FAA2F;YACzF,oFAAoF;YACpF,0FAA0F;YAC1F,qBAAqB,CACxB,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,OAAO,qBAAqB;IAChC,KAAK,CAAC,SAAS,CAAC,KAA0B;QACxC,MAAM,YAAY,GAAG,gBAAgB,EAAE,CAAC;QACxC,IAAI,QAAQ,GAAG,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;QAEtD,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC1E,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE;gBAClE,GAAG,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,IAAI,OAAO;aACjC,CAAC,CAAC;QACL,CAAC;QAED,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAClD,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,CAAC;QAE5C,OAAO;YACL,KAAK,EAAE,IAAI,UAAU,CAAC,SAAS,CAAC;YAChC,WAAW,EAAE,sBAAsB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;SACzD,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Public surface (barrel) for the `media` library.
|
|
3
|
+
*
|
|
4
|
+
* A module's public contract is its `index.ts` — deep imports from outside
|
|
5
|
+
* this directory should go through here.
|
|
6
|
+
*
|
|
7
|
+
* See `types.ts` and `media-service.ts` file headers for the disclosed scope
|
|
8
|
+
* adjustments this walking-skeleton build makes relative to the full
|
|
9
|
+
* design (bespoke table instead of generic entries; no origin isolation or
|
|
10
|
+
* ingress policy). Blob GC (`blob-gc.ts`) IS built for real within its own
|
|
11
|
+
* disclosed scope — see that file's header for what's still stubbed
|
|
12
|
+
* (`entry_refs`, retained snapshots, the monthly orphan sweep).
|
|
13
|
+
*/
|
|
14
|
+
export type { MediaStatus, MediaSource, MediaRecord, AssetBlobStatus, AssetBlobRecord, AssetRenditionRecord, BlobGcJournalEntry, } from "./types.js";
|
|
15
|
+
export { MediaNotFoundError, MediaValidationError, MediaConflictError, MediaSourceImmutableError, MediaStillReferencedError, } from "./types.js";
|
|
16
|
+
export type { MediaRepoPort, AssetBlobRepoPort, AssetRenditionRepoPort, BlobStorePort, BlobGcJournalRepoPort, PutBlobInput, TransformDefinitionRepoPort, } from "./ports.js";
|
|
17
|
+
export { computeBlobStorageKey } from "./blob-key.js";
|
|
18
|
+
export { InMemoryMediaRepo, InMemoryAssetBlobRepo, InMemoryAssetRenditionRepo, InMemoryBlobGcJournalRepo, InMemoryTransformDefinitionRepo, } from "./repo.memory.js";
|
|
19
|
+
export { withSha256Lock } from "./blob-gc-lock.js";
|
|
20
|
+
export { DEFAULT_GC_GRACE_MS, resolveGcGraceMs, isBlobUnreferenced, tombstoneBlobIfUnreferenced, runBlobGcDeletePass, runBlobGcUnlinkPass, runBlobGcCycle, runMonthlyOrphanSweepStub, } from "./blob-gc.js";
|
|
21
|
+
export { InMemoryBlobStore } from "./blob-store.memory.js";
|
|
22
|
+
export { LocalFsBlobStore, type LocalFsBlobStoreDeps } from "./blob-store.fs.js";
|
|
23
|
+
export { DEFAULT_MAX_UPLOAD_BYTES, DEFAULT_ALLOWED_MIME_TYPES, resolveWriteOnceSource, uploadMedia, listMedia, getMediaById, updateMediaMetadata, trashMedia, purgeMedia, type UploadMediaInput, type UploadMediaDeps, type UpdateMediaMetadataInput, } from "./media-service.js";
|
|
24
|
+
export type { TransformFit, TransformFormat, TransformParams, TransformDefinitionRecord, } from "./transform-types.js";
|
|
25
|
+
export { TransformValidationError, mimeForTransformFormat, MAX_TRANSFORM_DIMENSION_PX } from "./transform-types.js";
|
|
26
|
+
export { withRenditionLock, withTransformRegistryLock } from "./transform-lock.js";
|
|
27
|
+
export { registerTransform, getLatestTransformDefinition, isLatestTransformVersion, isReferencedByPublishedContent, type RegisterTransformInput, type RegisterTransformDeps, } from "./transform-registry.js";
|
|
28
|
+
export { resolveMediaRendition, type ResolveMediaRenditionDeps, type ResolveMediaRenditionInput, type ResolveMediaRenditionResult, } from "./rendition-service.js";
|
|
29
|
+
export type { ImageTransformerPort, TransformImageInput, TransformImageOutput } from "./image-transformer.js";
|
|
30
|
+
export { InMemoryImageTransformer } from "./image-transformer.js";
|
|
31
|
+
export { SharpImageTransformer, ImageTransformUnavailableError } from "./image-transformer.sharp.js";
|
|
32
|
+
export { sniffContentType, type SniffedContentType } from "./content-type-sniffer.js";
|
|
33
|
+
/** The agent-tool catalog for this domain (see `agent-tools.ts` for what is deliberately omitted). */
|
|
34
|
+
export { mediaAgentToolCatalog, type AgentToolDefinition as MediaAgentToolDefinition, type AgentToolSideEffect as MediaAgentToolSideEffect, type AgentToolActorClassRule as MediaAgentToolActorClassRule, } from "./agent-tools.js";
|
|
35
|
+
/**
|
|
36
|
+
* The agent-tool wiring for this domain.
|
|
37
|
+
*
|
|
38
|
+
* `MediaToolDeps` is declared structurally rather than derived from any host's request-scoped
|
|
39
|
+
* dependency bag, which is what lets a host satisfy it by passing whatever object it already has —
|
|
40
|
+
* the shape is the contract, so no host type needs to be named here.
|
|
41
|
+
*/
|
|
42
|
+
export { buildMediaRegistrations, mediaDerivedRisk, type MediaToolDeps, } from "./tool-registrations.js";
|
|
43
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,YAAY,EACV,WAAW,EACX,WAAW,EACX,WAAW,EACX,eAAe,EACf,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,sBAAsB,EACtB,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,2BAA2B,GAC5B,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,KAAK,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAEjF,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,WAAW,EACX,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,UAAU,EACV,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,wBAAwB,GAC9B,MAAM,oBAAoB,CAAC;AAS5B,YAAY,EACV,YAAY,EACZ,eAAe,EACf,eAAe,EACf,yBAAyB,GAC1B,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEpH,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,wBAAwB,EACxB,8BAA8B,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,qBAAqB,GAC3B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,qBAAqB,EACrB,KAAK,yBAAyB,EAC9B,KAAK,0BAA0B,EAC/B,KAAK,2BAA2B,GACjC,MAAM,wBAAwB,CAAC;AAEhC,YAAY,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9G,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAOrG,OAAO,EAAE,gBAAgB,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEtF,sGAAsG;AACtG,OAAO,EACL,qBAAqB,EACrB,KAAK,mBAAmB,IAAI,wBAAwB,EACpD,KAAK,mBAAmB,IAAI,wBAAwB,EACpD,KAAK,uBAAuB,IAAI,4BAA4B,GAC7D,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export { MediaNotFoundError, MediaValidationError, MediaConflictError, MediaSourceImmutableError, MediaStillReferencedError, } from "./types.js";
|
|
2
|
+
export { computeBlobStorageKey } from "./blob-key.js";
|
|
3
|
+
export { InMemoryMediaRepo, InMemoryAssetBlobRepo, InMemoryAssetRenditionRepo, InMemoryBlobGcJournalRepo, InMemoryTransformDefinitionRepo, } from "./repo.memory.js";
|
|
4
|
+
export { withSha256Lock } from "./blob-gc-lock.js";
|
|
5
|
+
export { DEFAULT_GC_GRACE_MS, resolveGcGraceMs, isBlobUnreferenced, tombstoneBlobIfUnreferenced, runBlobGcDeletePass, runBlobGcUnlinkPass, runBlobGcCycle, runMonthlyOrphanSweepStub, } from "./blob-gc.js";
|
|
6
|
+
export { InMemoryBlobStore } from "./blob-store.memory.js";
|
|
7
|
+
export { LocalFsBlobStore } from "./blob-store.fs.js";
|
|
8
|
+
export { DEFAULT_MAX_UPLOAD_BYTES, DEFAULT_ALLOWED_MIME_TYPES, resolveWriteOnceSource, uploadMedia, listMedia, getMediaById, updateMediaMetadata, trashMedia, purgeMedia, } from "./media-service.js";
|
|
9
|
+
export { TransformValidationError, mimeForTransformFormat, MAX_TRANSFORM_DIMENSION_PX } from "./transform-types.js";
|
|
10
|
+
export { withRenditionLock, withTransformRegistryLock } from "./transform-lock.js";
|
|
11
|
+
export { registerTransform, getLatestTransformDefinition, isLatestTransformVersion, isReferencedByPublishedContent, } from "./transform-registry.js";
|
|
12
|
+
export { resolveMediaRendition, } from "./rendition-service.js";
|
|
13
|
+
export { InMemoryImageTransformer } from "./image-transformer.js";
|
|
14
|
+
export { SharpImageTransformer, ImageTransformUnavailableError } from "./image-transformer.sharp.js";
|
|
15
|
+
// -----------------------------------------------------------------------------
|
|
16
|
+
// Original-bytes admin preview route support. See `content-type-sniffer.ts`'s
|
|
17
|
+
// file header for the disclosed scope: an allowlist magic-byte sniffer, not a
|
|
18
|
+
// general-purpose one.
|
|
19
|
+
// -----------------------------------------------------------------------------
|
|
20
|
+
export { sniffContentType } from "./content-type-sniffer.js";
|
|
21
|
+
/** The agent-tool catalog for this domain (see `agent-tools.ts` for what is deliberately omitted). */
|
|
22
|
+
export { mediaAgentToolCatalog, } from "./agent-tools.js";
|
|
23
|
+
/**
|
|
24
|
+
* The agent-tool wiring for this domain.
|
|
25
|
+
*
|
|
26
|
+
* `MediaToolDeps` is declared structurally rather than derived from any host's request-scoped
|
|
27
|
+
* dependency bag, which is what lets a host satisfy it by passing whatever object it already has —
|
|
28
|
+
* the shape is the contract, so no host type needs to be named here.
|
|
29
|
+
*/
|
|
30
|
+
export { buildMediaRegistrations, mediaDerivedRisk, } from "./tool-registrations.js";
|
|
31
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/media/index.ts"],"names":[],"mappings":"AAuBA,OAAO,EACL,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,YAAY,CAAC;AAYpB,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAEtD,OAAO,EACL,iBAAiB,EACjB,qBAAqB,EACrB,0BAA0B,EAC1B,yBAAyB,EACzB,+BAA+B,GAChC,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEnD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,2BAA2B,EAC3B,mBAAmB,EACnB,mBAAmB,EACnB,cAAc,EACd,yBAAyB,GAC1B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAA6B,MAAM,oBAAoB,CAAC;AAEjF,OAAO,EACL,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,WAAW,EACX,SAAS,EACT,YAAY,EACZ,mBAAmB,EACnB,UAAU,EACV,UAAU,GAIX,MAAM,oBAAoB,CAAC;AAe5B,OAAO,EAAE,wBAAwB,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAEpH,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAEnF,OAAO,EACL,iBAAiB,EACjB,4BAA4B,EAC5B,wBAAwB,EACxB,8BAA8B,GAG/B,MAAM,yBAAyB,CAAC;AAEjC,OAAO,EACL,qBAAqB,GAItB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,wBAAwB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAE,qBAAqB,EAAE,8BAA8B,EAAE,MAAM,8BAA8B,CAAC;AAErG,gFAAgF;AAChF,8EAA8E;AAC9E,8EAA8E;AAC9E,uBAAuB;AACvB,gFAAgF;AAChF,OAAO,EAAE,gBAAgB,EAA2B,MAAM,2BAA2B,CAAC;AAEtF,sGAAsG;AACtG,OAAO,EACL,qBAAqB,GAItB,MAAM,kBAAkB,CAAC;AAE1B;;;;;;GAMG;AACH,OAAO,EACL,uBAAuB,EACvB,gBAAgB,GAEjB,MAAM,yBAAyB,CAAC"}
|