@endora-commerce/mod-assets-library 0.0.0-stage → 0.100.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 +21 -0
- package/README.md +61 -2
- package/dist/admin/api/assets-library-client.d.ts +29 -0
- package/dist/admin/api/assets-library-client.d.ts.map +1 -0
- package/dist/admin/api/assets-library-client.js +70 -0
- package/dist/admin/api/assets-library-client.js.map +1 -0
- package/dist/admin/components/AssetDetailDrawer.d.ts +8 -0
- package/dist/admin/components/AssetDetailDrawer.d.ts.map +1 -0
- package/dist/admin/components/AssetDetailDrawer.js +96 -0
- package/dist/admin/components/AssetDetailDrawer.js.map +1 -0
- package/dist/admin/components/FolderTree.d.ts +13 -0
- package/dist/admin/components/FolderTree.d.ts.map +1 -0
- package/dist/admin/components/FolderTree.js +71 -0
- package/dist/admin/components/FolderTree.js.map +1 -0
- package/dist/admin/index.d.ts +44 -0
- package/dist/admin/index.d.ts.map +1 -0
- package/dist/admin/index.js +46 -0
- package/dist/admin/index.js.map +1 -0
- package/dist/admin/pages/LibraryPage.d.ts +9 -0
- package/dist/admin/pages/LibraryPage.d.ts.map +1 -0
- package/dist/admin/pages/LibraryPage.js +163 -0
- package/dist/admin/pages/LibraryPage.js.map +1 -0
- package/dist/backend/entities/asset-folder.entity.d.ts +16 -0
- package/dist/backend/entities/asset-folder.entity.d.ts.map +1 -0
- package/dist/backend/entities/asset-folder.entity.js +57 -0
- package/dist/backend/entities/asset-folder.entity.js.map +1 -0
- package/dist/backend/entities/asset.entity.d.ts +38 -0
- package/dist/backend/entities/asset.entity.d.ts.map +1 -0
- package/dist/backend/entities/asset.entity.js +128 -0
- package/dist/backend/entities/asset.entity.js.map +1 -0
- package/dist/backend/index.d.ts +57 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +150 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/jobs/hard-delete-asset.job.d.ts +18 -0
- package/dist/backend/jobs/hard-delete-asset.job.d.ts.map +1 -0
- package/dist/backend/jobs/hard-delete-asset.job.js +91 -0
- package/dist/backend/jobs/hard-delete-asset.job.js.map +1 -0
- package/dist/backend/plugin.d.ts +47 -0
- package/dist/backend/plugin.d.ts.map +1 -0
- package/dist/backend/plugin.js +96 -0
- package/dist/backend/plugin.js.map +1 -0
- package/dist/backend/routes.admin.d.ts +15 -0
- package/dist/backend/routes.admin.d.ts.map +1 -0
- package/dist/backend/routes.admin.js +189 -0
- package/dist/backend/routes.admin.js.map +1 -0
- package/dist/backend/routes.public.d.ts +14 -0
- package/dist/backend/routes.public.d.ts.map +1 -0
- package/dist/backend/routes.public.js +99 -0
- package/dist/backend/routes.public.js.map +1 -0
- package/dist/backend/services/asset-read-port.d.ts +103 -0
- package/dist/backend/services/asset-read-port.d.ts.map +1 -0
- package/dist/backend/services/asset-read-port.js +167 -0
- package/dist/backend/services/asset-read-port.js.map +1 -0
- package/dist/backend/services/assets-library.service.d.ts +76 -0
- package/dist/backend/services/assets-library.service.d.ts.map +1 -0
- package/dist/backend/services/assets-library.service.js +261 -0
- package/dist/backend/services/assets-library.service.js.map +1 -0
- package/dist/backend/services/cms-body-resolver.d.ts +6 -0
- package/dist/backend/services/cms-body-resolver.d.ts.map +1 -0
- package/dist/backend/services/cms-body-resolver.js +44 -0
- package/dist/backend/services/cms-body-resolver.js.map +1 -0
- package/dist/backend/services/folders.service.d.ts +29 -0
- package/dist/backend/services/folders.service.d.ts.map +1 -0
- package/dist/backend/services/folders.service.js +231 -0
- package/dist/backend/services/folders.service.js.map +1 -0
- package/dist/backend/services/hmac.d.ts +28 -0
- package/dist/backend/services/hmac.d.ts.map +1 -0
- package/dist/backend/services/hmac.js +50 -0
- package/dist/backend/services/hmac.js.map +1 -0
- package/dist/backend/services/reference-registry.d.ts +36 -0
- package/dist/backend/services/reference-registry.d.ts.map +1 -0
- package/dist/backend/services/reference-registry.js +63 -0
- package/dist/backend/services/reference-registry.js.map +1 -0
- package/dist/backend/services/storage/adapter-registry.d.ts +77 -0
- package/dist/backend/services/storage/adapter-registry.d.ts.map +1 -0
- package/dist/backend/services/storage/adapter-registry.js +95 -0
- package/dist/backend/services/storage/adapter-registry.js.map +1 -0
- package/dist/backend/services/storage/errors.d.ts +18 -0
- package/dist/backend/services/storage/errors.d.ts.map +1 -0
- package/dist/backend/services/storage/errors.js +30 -0
- package/dist/backend/services/storage/errors.js.map +1 -0
- package/dist/backend/services/storage/gcs-adapter.d.ts +42 -0
- package/dist/backend/services/storage/gcs-adapter.d.ts.map +1 -0
- package/dist/backend/services/storage/gcs-adapter.js +106 -0
- package/dist/backend/services/storage/gcs-adapter.js.map +1 -0
- package/dist/backend/services/storage/legacy-resolver.d.ts +15 -0
- package/dist/backend/services/storage/legacy-resolver.d.ts.map +1 -0
- package/dist/backend/services/storage/legacy-resolver.js +32 -0
- package/dist/backend/services/storage/legacy-resolver.js.map +1 -0
- package/dist/backend/services/storage/local-fs-adapter.d.ts +59 -0
- package/dist/backend/services/storage/local-fs-adapter.d.ts.map +1 -0
- package/dist/backend/services/storage/local-fs-adapter.js +153 -0
- package/dist/backend/services/storage/local-fs-adapter.js.map +1 -0
- package/dist/backend/services/storage/locator.d.ts +5 -0
- package/dist/backend/services/storage/locator.d.ts.map +1 -0
- package/dist/backend/services/storage/locator.js +16 -0
- package/dist/backend/services/storage/locator.js.map +1 -0
- package/dist/backend/services/storage/object-storage-port.d.ts +46 -0
- package/dist/backend/services/storage/object-storage-port.d.ts.map +1 -0
- package/dist/backend/services/storage/object-storage-port.js +78 -0
- package/dist/backend/services/storage/object-storage-port.js.map +1 -0
- package/dist/backend/services/storage/public-url-base.d.ts +50 -0
- package/dist/backend/services/storage/public-url-base.d.ts.map +1 -0
- package/dist/backend/services/storage/public-url-base.js +70 -0
- package/dist/backend/services/storage/public-url-base.js.map +1 -0
- package/dist/backend/services/storage/s3-adapter.d.ts +50 -0
- package/dist/backend/services/storage/s3-adapter.d.ts.map +1 -0
- package/dist/backend/services/storage/s3-adapter.js +110 -0
- package/dist/backend/services/storage/s3-adapter.js.map +1 -0
- package/dist/backend/services/storage/settings-view.d.ts +4 -0
- package/dist/backend/services/storage/settings-view.d.ts.map +1 -0
- package/dist/backend/services/storage/settings-view.js +73 -0
- package/dist/backend/services/storage/settings-view.js.map +1 -0
- package/dist/backend/services/storage/storage-adapter.d.ts +62 -0
- package/dist/backend/services/storage/storage-adapter.d.ts.map +1 -0
- package/dist/backend/services/storage/storage-adapter.js +10 -0
- package/dist/backend/services/storage/storage-adapter.js.map +1 -0
- package/dist/backend/services/upload-pipeline.d.ts +41 -0
- package/dist/backend/services/upload-pipeline.d.ts.map +1 -0
- package/dist/backend/services/upload-pipeline.js +231 -0
- package/dist/backend/services/upload-pipeline.js.map +1 -0
- package/dist/manifest.d.ts +185 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/manifest.js +229 -0
- package/dist/manifest.js.map +1 -0
- package/dist/migrations/20260505T102206_assets_library_init.d.ts +35 -0
- package/dist/migrations/20260505T102206_assets_library_init.d.ts.map +1 -0
- package/dist/migrations/20260505T102206_assets_library_init.js +132 -0
- package/dist/migrations/20260505T102206_assets_library_init.js.map +1 -0
- package/dist/migrations/index.d.ts +27 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +29 -0
- package/dist/migrations/index.js.map +1 -0
- package/docs/assets-library/index.md +125 -0
- package/i18n/en.json +54 -0
- package/i18n/pl.json +54 -0
- package/package.json +99 -3
- package/tailwind.css +14 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.admin.js","sourceRoot":"","sources":["../../src/backend/routes.admin.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { FastifyInstance } from 'fastify';
|
|
2
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
3
|
+
import type { AdapterRegistry } from './services/storage/adapter-registry.js';
|
|
4
|
+
import type { AssetsLibraryService } from './services/assets-library.service.js';
|
|
5
|
+
import type { HmacSigner } from './services/hmac.js';
|
|
6
|
+
export interface PublicRoutesDeps {
|
|
7
|
+
service: AssetsLibraryService;
|
|
8
|
+
adapters: AdapterRegistry;
|
|
9
|
+
emFactory: () => EntityManager;
|
|
10
|
+
/** Provider so tests that never serve files don't pay env-var cost. */
|
|
11
|
+
signer: () => HmacSigner;
|
|
12
|
+
}
|
|
13
|
+
export declare function registerAssetsLibraryPublicRoutes(app: FastifyInstance, deps: PublicRoutesDeps): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=routes.public.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.public.d.ts","sourceRoot":"","sources":["../../src/backend/routes.public.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAgB,MAAM,SAAS,CAAC;AAC7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAM3D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAC;AAC9E,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,oBAAoB,CAAC;IAC9B,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,MAAM,aAAa,CAAC;IAC/B,uEAAuE;IACvE,MAAM,EAAE,MAAM,UAAU,CAAC;CAC1B;AAED,wBAAsB,iCAAiC,CACrD,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,gBAAgB,GACrB,OAAO,CAAC,IAAI,CAAC,CAqGf"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Public file-serving route for the Assets Library — feature 013 / US1.
|
|
2
|
+
// Used by the storefront for assets stored on the local-FS adapter.
|
|
3
|
+
// Cloud adapters (S3 / GCS) bypass this route entirely — their public URLs
|
|
4
|
+
// point at the bucket directly and their private URLs are signed by the
|
|
5
|
+
// vendor SDK; the storefront fetches them without touching this code path.
|
|
6
|
+
//
|
|
7
|
+
// Behaviour:
|
|
8
|
+
// public assets → no auth, long Cache-Control
|
|
9
|
+
// private assets → require valid HMAC token (?token=&exp=)
|
|
10
|
+
// soft-deleted → 410 ASSET_GONE (so still-live storefront caches degrade gracefully)
|
|
11
|
+
// missing file → 404 ASSET_FILE_MISSING
|
|
12
|
+
import { ERROR_CODES } from '@endora-commerce/contracts';
|
|
13
|
+
import { HttpError } from '@endora-commerce/platform/http';
|
|
14
|
+
import { Asset } from './entities/asset.entity.js';
|
|
15
|
+
import { LocalFsStorageAdapter } from './services/storage/local-fs-adapter.js';
|
|
16
|
+
export async function registerAssetsLibraryPublicRoutes(app, deps) {
|
|
17
|
+
app.get('/assets/file/:assetId', { config: { streamingResponse: true } }, async (req, reply) => {
|
|
18
|
+
const em = deps.emFactory();
|
|
19
|
+
const a = await em.findOne(Asset, { id: req.params.assetId });
|
|
20
|
+
if (!a) {
|
|
21
|
+
throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, 'Asset not found.');
|
|
22
|
+
}
|
|
23
|
+
if (a.deletedAt) {
|
|
24
|
+
throw new HttpError(410, ERROR_CODES.ASSET_GONE, 'Asset has been deleted.');
|
|
25
|
+
}
|
|
26
|
+
// This route only serves bytes from the local-FS adapter. Cloud
|
|
27
|
+
// assets are always reached via the bucket URL or signed URL — they
|
|
28
|
+
// never hit this endpoint.
|
|
29
|
+
if (a.storageBackend !== 'local') {
|
|
30
|
+
// Redirect to the resolved URL so a misconfigured client falls back
|
|
31
|
+
// to the canonical serving path.
|
|
32
|
+
const resolved = await deps.service.resolveUrl(a.id);
|
|
33
|
+
reply.redirect(resolved.url, 302);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// Visibility / token check.
|
|
37
|
+
if (a.visibility === 'private') {
|
|
38
|
+
const signer = deps.signer();
|
|
39
|
+
const exp = Number(req.query.exp);
|
|
40
|
+
const token = String(req.query.token ?? '');
|
|
41
|
+
const ok = signer.verify({
|
|
42
|
+
assetId: a.id,
|
|
43
|
+
token,
|
|
44
|
+
exp,
|
|
45
|
+
nowSec: Math.floor(Date.now() / 1000),
|
|
46
|
+
});
|
|
47
|
+
if (!ok) {
|
|
48
|
+
throw new HttpError(403, ERROR_CODES.ASSET_ACCESS_DENIED, 'Access denied.');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
const adapter = await deps.adapters.getForBackend('local');
|
|
52
|
+
if (!(adapter instanceof LocalFsStorageAdapter)) {
|
|
53
|
+
throw new HttpError(500, ERROR_CODES.INTERNAL, 'Local-FS adapter is not currently active.');
|
|
54
|
+
}
|
|
55
|
+
// ETag / 304 short-circuit.
|
|
56
|
+
const etag = `"${a.id}-${Math.floor(a.updatedAt.getTime() / 1000)}"`;
|
|
57
|
+
const ifNoneMatch = req.headers['if-none-match'];
|
|
58
|
+
if (typeof ifNoneMatch === 'string' && ifNoneMatch === etag) {
|
|
59
|
+
return reply.status(304).send();
|
|
60
|
+
}
|
|
61
|
+
// Stream open. open() throws on missing file → 404 ASSET_FILE_MISSING.
|
|
62
|
+
let stream;
|
|
63
|
+
try {
|
|
64
|
+
stream = await adapter.open({ locator: a.storageLocator || a.storageUrl });
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
throw new HttpError(404, ERROR_CODES.ASSET_FILE_MISSING, 'Underlying file is missing.');
|
|
68
|
+
}
|
|
69
|
+
// Standard headers.
|
|
70
|
+
reply.header('Content-Type', a.mimeType);
|
|
71
|
+
// sizeBytes is mapped as bigint at the DB layer; coerce to string for
|
|
72
|
+
// the Content-Length header (Node's HTTP layer rejects bigint values).
|
|
73
|
+
// Only set it when the recorded size is meaningful — a stale/legacy `0`
|
|
74
|
+
// (uploads that never captured a byte count) would otherwise tell the
|
|
75
|
+
// browser the body is empty and produce a broken/blank image. Omitting
|
|
76
|
+
// the header lets Fastify stream the file to EOF.
|
|
77
|
+
if (Number(a.sizeBytes) > 0) {
|
|
78
|
+
reply.header('Content-Length', String(a.sizeBytes));
|
|
79
|
+
}
|
|
80
|
+
reply.header('ETag', etag);
|
|
81
|
+
reply.header('Cache-Control', a.visibility === 'public'
|
|
82
|
+
? 'public, max-age=31536000, immutable'
|
|
83
|
+
: 'private, no-store, max-age=0');
|
|
84
|
+
// Public assets are embedded by the storefront and admin, which run on a
|
|
85
|
+
// different origin than the backend. Helmet's default
|
|
86
|
+
// `Cross-Origin-Resource-Policy: same-origin` would block those
|
|
87
|
+
// cross-origin <img> loads, so relax it to `cross-origin` for public
|
|
88
|
+
// assets (private assets keep the stricter default).
|
|
89
|
+
if (a.visibility === 'public') {
|
|
90
|
+
reply.header('Cross-Origin-Resource-Policy', 'cross-origin');
|
|
91
|
+
}
|
|
92
|
+
const dispoMode = req.query.download === '1' ? 'attachment' : 'inline';
|
|
93
|
+
const safeName = a.filename.replace(/[\r\n";]/g, '_');
|
|
94
|
+
reply.header('Content-Disposition', `${dispoMode}; filename="${safeName}"`);
|
|
95
|
+
// Fastify will pipe a Readable through to the response.
|
|
96
|
+
return reply.send(stream);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=routes.public.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.public.js","sourceRoot":"","sources":["../../src/backend/routes.public.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,oEAAoE;AACpE,2EAA2E;AAC3E,wEAAwE;AACxE,2EAA2E;AAC3E,EAAE;AACF,aAAa;AACb,iDAAiD;AACjD,6DAA6D;AAC7D,yFAAyF;AACzF,4CAA4C;AAI5C,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AAEzD,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAa/E,MAAM,CAAC,KAAK,UAAU,iCAAiC,CACrD,GAAoB,EACpB,IAAsB;IAEtB,GAAG,CAAC,GAAG,CAIL,uBAAuB,EACvB,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,EAAE,EACvC,KAAK,EAAE,GAAG,EAAE,KAAmB,EAAE,EAAE;QACjC,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,EAAE,CAAC;YACP,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,eAAe,EAAE,kBAAkB,CAAC,CAAC;QAC5E,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;YAChB,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,UAAU,EAAE,yBAAyB,CAAC,CAAC;QAC9E,CAAC;QAED,gEAAgE;QAChE,oEAAoE;QACpE,2BAA2B;QAC3B,IAAI,CAAC,CAAC,cAAc,KAAK,OAAO,EAAE,CAAC;YACjC,oEAAoE;YACpE,iCAAiC;YACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACrD,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YAClC,OAAO;QACT,CAAC;QAED,4BAA4B;QAC5B,IAAI,CAAC,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAClC,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;YAC5C,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC;gBACvB,OAAO,EAAE,CAAC,CAAC,EAAE;gBACb,KAAK;gBACL,GAAG;gBACH,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;aACtC,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC;YAC9E,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC3D,IAAI,CAAC,CAAC,OAAO,YAAY,qBAAqB,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,QAAQ,EACpB,2CAA2C,CAC5C,CAAC;QACJ,CAAC;QAED,4BAA4B;QAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC;QACrE,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QACjD,IAAI,OAAO,WAAW,KAAK,QAAQ,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;YAC5D,OAAO,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;QAClC,CAAC;QAED,uEAAuE;QACvE,IAAI,MAAM,CAAC;QACX,IAAI,CAAC;YACH,MAAM,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,cAAc,IAAI,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;QAC7E,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,kBAAkB,EAAE,6BAA6B,CAAC,CAAC;QAC1F,CAAC;QAED,oBAAoB;QACpB,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC;QACzC,sEAAsE;QACtE,uEAAuE;QACvE,wEAAwE;QACxE,sEAAsE;QACtE,uEAAuE;QACvE,kDAAkD;QAClD,IAAI,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5B,KAAK,CAAC,MAAM,CAAC,gBAAgB,EAAE,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;QACtD,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC3B,KAAK,CAAC,MAAM,CACV,eAAe,EACf,CAAC,CAAC,UAAU,KAAK,QAAQ;YACvB,CAAC,CAAC,qCAAqC;YACvC,CAAC,CAAC,8BAA8B,CACnC,CAAC;QACF,yEAAyE;QACzE,sDAAsD;QACtD,gEAAgE;QAChE,qEAAqE;QACrE,qDAAqD;QACrD,IAAI,CAAC,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YAC9B,KAAK,CAAC,MAAM,CAAC,8BAA8B,EAAE,cAAc,CAAC,CAAC;QAC/D,CAAC;QACD,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;QACvE,MAAM,QAAQ,GAAG,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC;QACtD,KAAK,CAAC,MAAM,CAAC,qBAAqB,EAAE,GAAG,SAAS,eAAe,QAAQ,GAAG,CAAC,CAAC;QAC5E,wDAAwD;QACxD,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5B,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import type { AssetBytes, AssetByteStream, AssetReadPort, AssetRecord, ObjectStorageBackendCode, StorageBackendCode } from '@endora-commerce/contracts';
|
|
3
|
+
import { Asset } from '../entities/asset.entity.js';
|
|
4
|
+
import type { StorageResolveUrlInput, StorageResolveUrlOutput } from './storage/storage-adapter.js';
|
|
5
|
+
/**
|
|
6
|
+
* The narrow slice of the adapter registry {@link AssetReadService} needs — the
|
|
7
|
+
* URL builder of whichever backend owns an object's bytes, and, for a backend
|
|
8
|
+
* that is a real object store, the reader that opens them.
|
|
9
|
+
*
|
|
10
|
+
* Declared here rather than taking `AdapterRegistry` so that the read model can
|
|
11
|
+
* be unit-tested over a stub, and so that the two capabilities it has over the
|
|
12
|
+
* `assets` table are visible in its constructor.
|
|
13
|
+
*
|
|
14
|
+
* **Two overloads, narrowest first**, because `AdapterRegistry` has exactly
|
|
15
|
+
* this shape and for the reason it has it: `legacy` is not a store — it
|
|
16
|
+
* resolves the URL of a pre-013 row this platform did not issue and can open
|
|
17
|
+
* nothing — so `open` exists only on the arm a `legacy` code cannot reach
|
|
18
|
+
* (`ObjectStoragePort`'s doc block, point 3). Widest-first would hand every
|
|
19
|
+
* call the arm without `open` and put the probe back at the call site, which is
|
|
20
|
+
* the thing the port removes.
|
|
21
|
+
*/
|
|
22
|
+
export interface AssetStorageRegistry {
|
|
23
|
+
getForBackend(backend: ObjectStorageBackendCode): Promise<{
|
|
24
|
+
resolveUrl(input: StorageResolveUrlInput): StorageResolveUrlOutput | Promise<StorageResolveUrlOutput>;
|
|
25
|
+
open(input: {
|
|
26
|
+
locator: string;
|
|
27
|
+
}): Promise<AssetByteStream>;
|
|
28
|
+
}>;
|
|
29
|
+
getForBackend(backend: StorageBackendCode): Promise<{
|
|
30
|
+
resolveUrl(input: StorageResolveUrlInput): StorageResolveUrlOutput | Promise<StorageResolveUrlOutput>;
|
|
31
|
+
}>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* The row-level read model `assets_library` publishes (feature 075, Phase P).
|
|
35
|
+
*
|
|
36
|
+
* Five inbound sites read the `Asset` entity, and all five ask the same thing
|
|
37
|
+
* before attaching an id an admin supplied: does this asset exist, and is it
|
|
38
|
+
* the right kind? `catalog`'s gallery, attachments and product links do it
|
|
39
|
+
* three times over, `orders` once for invoice branding.
|
|
40
|
+
*
|
|
41
|
+
* `sizeBytes` stays a string: the column is `bigint`, and a `number` cannot
|
|
42
|
+
* hold one past 2^53.
|
|
43
|
+
*/
|
|
44
|
+
export declare class AssetReadService implements AssetReadPort {
|
|
45
|
+
private readonly emFactory;
|
|
46
|
+
/**
|
|
47
|
+
* Required, and a provider rather than the registry itself: the registry is
|
|
48
|
+
* built from settings and rebuilt when they change, so a captured one goes
|
|
49
|
+
* stale after an operator switches the active backend. Not optional — an
|
|
50
|
+
* argument whose omission is silent is how this module once shipped a
|
|
51
|
+
* permission gate that defaulted to permissive.
|
|
52
|
+
*/
|
|
53
|
+
private readonly adapters;
|
|
54
|
+
constructor(emFactory: () => EntityManager,
|
|
55
|
+
/**
|
|
56
|
+
* Required, and a provider rather than the registry itself: the registry is
|
|
57
|
+
* built from settings and rebuilt when they change, so a captured one goes
|
|
58
|
+
* stale after an operator switches the active backend. Not optional — an
|
|
59
|
+
* argument whose omission is silent is how this module once shipped a
|
|
60
|
+
* permission gate that defaulted to permissive.
|
|
61
|
+
*/
|
|
62
|
+
adapters: () => AssetStorageRegistry);
|
|
63
|
+
findById(id: string, options?: {
|
|
64
|
+
liveOnly?: boolean;
|
|
65
|
+
}): Promise<AssetRecord | null>;
|
|
66
|
+
findByIds(ids: readonly string[], options?: {
|
|
67
|
+
liveOnly?: boolean;
|
|
68
|
+
}): Promise<AssetRecord[]>;
|
|
69
|
+
/**
|
|
70
|
+
* FR-043's rule, answered where the information is.
|
|
71
|
+
*
|
|
72
|
+
* Only a live, `public` asset can have a stable URL, and only this module can
|
|
73
|
+
* say so: a consumer holding an asset id cannot tell a signed link from a
|
|
74
|
+
* permanent one. So the filter is here and the absence is the answer — see
|
|
75
|
+
* the port's contract.
|
|
76
|
+
*
|
|
77
|
+
* One query for the rows and a URL build per row. The adapters are cached by
|
|
78
|
+
* the registry and a *public* resolution is a string join in all four of
|
|
79
|
+
* them, so this issues no I/O beyond the read.
|
|
80
|
+
*/
|
|
81
|
+
resolvePublicUrls(assetIds: readonly string[]): Promise<Map<string, string>>;
|
|
82
|
+
/**
|
|
83
|
+
* The bytes of one live asset — the port's rule, answered where the storage
|
|
84
|
+
* layout is (`specs/110-instance-repository/` T118c).
|
|
85
|
+
*
|
|
86
|
+
* Three facts left a composition root to arrive here, and each of them is one
|
|
87
|
+
* line below. `legacy` is not a store, so a row on it has no bytes to open
|
|
88
|
+
* and answers `null` rather than being probed for an `open` method at the
|
|
89
|
+
* call site. The locator falls back to `storageUrl` for rows written before
|
|
90
|
+
* the column existed. And an adapter answers a stream, which the caller
|
|
91
|
+
* wanted whole.
|
|
92
|
+
*
|
|
93
|
+
* **The `catch` is the degrade, and it belongs here** (composition checklist
|
|
94
|
+
* item 7): a configured backend that will not stream is a document rendered
|
|
95
|
+
* without its decoration, and the caller — holding an asset id and nothing
|
|
96
|
+
* else — cannot tell that state from an asset that is not there. It is
|
|
97
|
+
* narrow on purpose: it covers the open and the drain, never the row read,
|
|
98
|
+
* which is this module's own `EntityManager` and whose failure is a real one.
|
|
99
|
+
*/
|
|
100
|
+
openAssetBytes(assetId: string): Promise<AssetBytes | null>;
|
|
101
|
+
}
|
|
102
|
+
export declare function toAssetRecord(asset: Asset): AssetRecord;
|
|
103
|
+
//# sourceMappingURL=asset-read-port.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-read-port.d.ts","sourceRoot":"","sources":["../../../src/backend/services/asset-read-port.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EACV,UAAU,EACV,eAAe,EACf,aAAa,EACb,WAAW,EACX,wBAAwB,EACxB,kBAAkB,EACnB,MAAM,4BAA4B,CAAC;AAEpC,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,KAAK,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAEpG;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,OAAO,EAAE,wBAAwB,GAAG,OAAO,CAAC;QACxD,UAAU,CAAC,KAAK,EAAE,sBAAsB,GAAG,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;QACtG,IAAI,CAAC,KAAK,EAAE;YAAE,OAAO,EAAE,MAAM,CAAA;SAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;KAC5D,CAAC,CAAC;IACH,aAAa,CACX,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC;QAAE,UAAU,CAAC,KAAK,EAAE,sBAAsB,GAAG,uBAAuB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAA;KAAE,CAAC,CAAC;CACvH;AAED;;;;;;;;;;GAUG;AACH,qBAAa,gBAAiB,YAAW,aAAa;IAElD,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBARR,SAAS,EAAE,MAAM,aAAa;IAC/C;;;;;;OAMG;IACc,QAAQ,EAAE,MAAM,oBAAoB;IAGjD,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAQnF,SAAS,CACb,GAAG,EAAE,SAAS,MAAM,EAAE,EACtB,OAAO,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,GAC/B,OAAO,CAAC,WAAW,EAAE,CAAC;IASzB;;;;;;;;;;;OAWG;IACG,iBAAiB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IA+BlF;;;;;;;;;;;;;;;;;OAiBG;IACG,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;CAqClE;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,WAAW,CAqBvD"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { rethrowIfModuleDisabled } from '@endora-commerce/platform/kernel';
|
|
2
|
+
import { Asset } from '../entities/asset.entity.js';
|
|
3
|
+
/**
|
|
4
|
+
* The row-level read model `assets_library` publishes (feature 075, Phase P).
|
|
5
|
+
*
|
|
6
|
+
* Five inbound sites read the `Asset` entity, and all five ask the same thing
|
|
7
|
+
* before attaching an id an admin supplied: does this asset exist, and is it
|
|
8
|
+
* the right kind? `catalog`'s gallery, attachments and product links do it
|
|
9
|
+
* three times over, `orders` once for invoice branding.
|
|
10
|
+
*
|
|
11
|
+
* `sizeBytes` stays a string: the column is `bigint`, and a `number` cannot
|
|
12
|
+
* hold one past 2^53.
|
|
13
|
+
*/
|
|
14
|
+
export class AssetReadService {
|
|
15
|
+
emFactory;
|
|
16
|
+
adapters;
|
|
17
|
+
constructor(emFactory,
|
|
18
|
+
/**
|
|
19
|
+
* Required, and a provider rather than the registry itself: the registry is
|
|
20
|
+
* built from settings and rebuilt when they change, so a captured one goes
|
|
21
|
+
* stale after an operator switches the active backend. Not optional — an
|
|
22
|
+
* argument whose omission is silent is how this module once shipped a
|
|
23
|
+
* permission gate that defaulted to permissive.
|
|
24
|
+
*/
|
|
25
|
+
adapters) {
|
|
26
|
+
this.emFactory = emFactory;
|
|
27
|
+
this.adapters = adapters;
|
|
28
|
+
}
|
|
29
|
+
async findById(id, options) {
|
|
30
|
+
const asset = await this.emFactory().findOne(Asset, {
|
|
31
|
+
id,
|
|
32
|
+
...(options?.liveOnly ? { deletedAt: null } : {}),
|
|
33
|
+
});
|
|
34
|
+
return asset ? toAssetRecord(asset) : null;
|
|
35
|
+
}
|
|
36
|
+
async findByIds(ids, options) {
|
|
37
|
+
if (ids.length === 0)
|
|
38
|
+
return [];
|
|
39
|
+
const assets = await this.emFactory().find(Asset, {
|
|
40
|
+
id: { $in: [...ids] },
|
|
41
|
+
...(options?.liveOnly ? { deletedAt: null } : {}),
|
|
42
|
+
});
|
|
43
|
+
return assets.map(toAssetRecord);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* FR-043's rule, answered where the information is.
|
|
47
|
+
*
|
|
48
|
+
* Only a live, `public` asset can have a stable URL, and only this module can
|
|
49
|
+
* say so: a consumer holding an asset id cannot tell a signed link from a
|
|
50
|
+
* permanent one. So the filter is here and the absence is the answer — see
|
|
51
|
+
* the port's contract.
|
|
52
|
+
*
|
|
53
|
+
* One query for the rows and a URL build per row. The adapters are cached by
|
|
54
|
+
* the registry and a *public* resolution is a string join in all four of
|
|
55
|
+
* them, so this issues no I/O beyond the read.
|
|
56
|
+
*/
|
|
57
|
+
async resolvePublicUrls(assetIds) {
|
|
58
|
+
const out = new Map();
|
|
59
|
+
if (assetIds.length === 0)
|
|
60
|
+
return out;
|
|
61
|
+
const registry = this.adapters();
|
|
62
|
+
const assets = await this.emFactory().find(Asset, {
|
|
63
|
+
id: { $in: [...assetIds] },
|
|
64
|
+
deletedAt: null,
|
|
65
|
+
visibility: 'public',
|
|
66
|
+
});
|
|
67
|
+
for (const asset of assets) {
|
|
68
|
+
const adapter = await registry.getForBackend(asset.storageBackend);
|
|
69
|
+
const resolved = await adapter.resolveUrl({
|
|
70
|
+
locator: asset.storageLocator || asset.storageUrl,
|
|
71
|
+
visibility: asset.visibility,
|
|
72
|
+
});
|
|
73
|
+
// The rule the port states, kept where the answer is rather than inferred
|
|
74
|
+
// from the filter above. **Measured**: with that filter in place this
|
|
75
|
+
// branch is unreachable — all four resolvers answer a `public` visibility
|
|
76
|
+
// with `expiresAt: null` as their first statement — and with it removed
|
|
77
|
+
// this branch is what still refuses a private asset. Two spellings of one
|
|
78
|
+
// rule is deliberate here and only here: a fifth backend, or a fifth
|
|
79
|
+
// visibility, changes which of the two is doing the work, and a feed that
|
|
80
|
+
// published an expiring link would not fail anywhere near this line.
|
|
81
|
+
if (resolved.expiresAt !== null)
|
|
82
|
+
continue;
|
|
83
|
+
out.set(asset.id, resolved.url);
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The bytes of one live asset — the port's rule, answered where the storage
|
|
89
|
+
* layout is (`specs/110-instance-repository/` T118c).
|
|
90
|
+
*
|
|
91
|
+
* Three facts left a composition root to arrive here, and each of them is one
|
|
92
|
+
* line below. `legacy` is not a store, so a row on it has no bytes to open
|
|
93
|
+
* and answers `null` rather than being probed for an `open` method at the
|
|
94
|
+
* call site. The locator falls back to `storageUrl` for rows written before
|
|
95
|
+
* the column existed. And an adapter answers a stream, which the caller
|
|
96
|
+
* wanted whole.
|
|
97
|
+
*
|
|
98
|
+
* **The `catch` is the degrade, and it belongs here** (composition checklist
|
|
99
|
+
* item 7): a configured backend that will not stream is a document rendered
|
|
100
|
+
* without its decoration, and the caller — holding an asset id and nothing
|
|
101
|
+
* else — cannot tell that state from an asset that is not there. It is
|
|
102
|
+
* narrow on purpose: it covers the open and the drain, never the row read,
|
|
103
|
+
* which is this module's own `EntityManager` and whose failure is a real one.
|
|
104
|
+
*/
|
|
105
|
+
async openAssetBytes(assetId) {
|
|
106
|
+
const asset = await this.emFactory().findOne(Asset, { id: assetId, deletedAt: null });
|
|
107
|
+
if (!asset)
|
|
108
|
+
return null;
|
|
109
|
+
// Narrowed here rather than probed at the caller: the overload's `open` arm
|
|
110
|
+
// is unreachable for `legacy` by construction.
|
|
111
|
+
if (asset.storageBackend === 'legacy')
|
|
112
|
+
return null;
|
|
113
|
+
try {
|
|
114
|
+
const store = await this.adapters().getForBackend(asset.storageBackend);
|
|
115
|
+
const stream = await store.open({ locator: asset.storageLocator || asset.storageUrl });
|
|
116
|
+
const chunks = [];
|
|
117
|
+
let length = 0;
|
|
118
|
+
for await (const chunk of stream) {
|
|
119
|
+
const bytes = typeof chunk === 'string' ? new TextEncoder().encode(chunk) : chunk;
|
|
120
|
+
chunks.push(bytes);
|
|
121
|
+
length += bytes.byteLength;
|
|
122
|
+
}
|
|
123
|
+
const bytes = new Uint8Array(length);
|
|
124
|
+
let offset = 0;
|
|
125
|
+
for (const chunk of chunks) {
|
|
126
|
+
bytes.set(chunk, offset);
|
|
127
|
+
offset += chunk.byteLength;
|
|
128
|
+
}
|
|
129
|
+
return { bytes, mimeType: asset.mimeType };
|
|
130
|
+
}
|
|
131
|
+
catch (error) {
|
|
132
|
+
// Narrow tolerance, and `rethrowIfModuleDisabled` is its first line by
|
|
133
|
+
// decision rather than by habit. The registry this reaches is this
|
|
134
|
+
// module's own and crosses no gate today, so the re-throw is unreachable;
|
|
135
|
+
// what it buys is that it stays unreachable *by construction* — a future
|
|
136
|
+
// adapter that resolved a port would otherwise have its "this capability
|
|
137
|
+
// is off" answer absorbed into "this asset has no bytes", which is the
|
|
138
|
+
// fail-open composition checklist item 7 refuses. A status-code test
|
|
139
|
+
// would not do: `ModuleDisabledError` is an `HttpError`.
|
|
140
|
+
rethrowIfModuleDisabled(error);
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
export function toAssetRecord(asset) {
|
|
146
|
+
return {
|
|
147
|
+
id: asset.id,
|
|
148
|
+
kind: asset.kind,
|
|
149
|
+
filename: asset.filename,
|
|
150
|
+
mimeType: asset.mimeType,
|
|
151
|
+
sizeBytes: asset.sizeBytes,
|
|
152
|
+
storageUrl: asset.storageUrl,
|
|
153
|
+
altText: asset.altText ?? null,
|
|
154
|
+
folderId: asset.folderId ?? null,
|
|
155
|
+
visibility: asset.visibility,
|
|
156
|
+
label: asset.label ?? null,
|
|
157
|
+
storageBackend: asset.storageBackend,
|
|
158
|
+
storageLocator: asset.storageLocator,
|
|
159
|
+
pendingCleanup: asset.pendingCleanup,
|
|
160
|
+
purgeAfterAt: asset.purgeAfterAt ?? null,
|
|
161
|
+
mimeTypeOverridden: asset.mimeTypeOverridden,
|
|
162
|
+
createdAt: asset.createdAt,
|
|
163
|
+
updatedAt: asset.updatedAt,
|
|
164
|
+
deletedAt: asset.deletedAt ?? null,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=asset-read-port.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-read-port.js","sourceRoot":"","sources":["../../../src/backend/services/asset-read-port.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { EntityManager } from '@mikro-orm/postgresql';
|
|
2
|
+
import { type AssetSummary, type AssetDetail } from '@endora-commerce/contracts';
|
|
3
|
+
import type { AdapterRegistry } from './storage/adapter-registry.js';
|
|
4
|
+
import type { AssetReferenceRegistry } from './reference-registry.js';
|
|
5
|
+
import { type UploadInput, type UploadPolicy } from './upload-pipeline.js';
|
|
6
|
+
import type { AuditPort } from '@endora-commerce/platform/kernel';
|
|
7
|
+
export declare class NotImplementedYet extends Error {
|
|
8
|
+
readonly name = "NotImplementedYet";
|
|
9
|
+
constructor(method: string);
|
|
10
|
+
}
|
|
11
|
+
export interface AssetsLibraryServiceDeps {
|
|
12
|
+
emFactory: () => EntityManager;
|
|
13
|
+
adapters: AdapterRegistry;
|
|
14
|
+
referenceRegistry: AssetReferenceRegistry;
|
|
15
|
+
/** Upload-policy provider — reads `assets.allowed_file_types` + max-size. */
|
|
16
|
+
loadUploadPolicy: () => Promise<UploadPolicy>;
|
|
17
|
+
/** Feature 054 — audits asset writes co-transactionally when provided. */
|
|
18
|
+
auditLog?: AuditPort;
|
|
19
|
+
}
|
|
20
|
+
export interface ListAssetsQuery {
|
|
21
|
+
folderId?: string | null | undefined;
|
|
22
|
+
q?: string | undefined;
|
|
23
|
+
mime?: string | undefined;
|
|
24
|
+
visibility?: 'public' | 'private' | undefined;
|
|
25
|
+
includeDeleted?: boolean | undefined;
|
|
26
|
+
cursor?: string | undefined;
|
|
27
|
+
limit?: number | undefined;
|
|
28
|
+
}
|
|
29
|
+
export declare class AssetsLibraryService {
|
|
30
|
+
#private;
|
|
31
|
+
private readonly deps;
|
|
32
|
+
private readonly pipeline;
|
|
33
|
+
constructor(deps: AssetsLibraryServiceDeps);
|
|
34
|
+
/** Upload entry point — runs the atomic put + insert + compensating-delete pipeline. */
|
|
35
|
+
upload(input: UploadInput): Promise<AssetDetail>;
|
|
36
|
+
/** Resolve the serving URL for an asset by id (public or private). */
|
|
37
|
+
resolveUrl(assetId: string, opts?: {
|
|
38
|
+
ttlSec?: number;
|
|
39
|
+
}): Promise<{
|
|
40
|
+
url: string;
|
|
41
|
+
expiresAt: Date | null;
|
|
42
|
+
}>;
|
|
43
|
+
getAsset(assetId: string): Promise<AssetDetail>;
|
|
44
|
+
listAssets(query: ListAssetsQuery): Promise<{
|
|
45
|
+
data: AssetSummary[];
|
|
46
|
+
nextCursor: string | null;
|
|
47
|
+
}>;
|
|
48
|
+
patchAsset(assetId: string, patch: {
|
|
49
|
+
filename?: string;
|
|
50
|
+
label?: string | null;
|
|
51
|
+
mimeType?: string;
|
|
52
|
+
visibility?: 'public' | 'private';
|
|
53
|
+
folderId?: string | null;
|
|
54
|
+
/**
|
|
55
|
+
* Per-language alternate text. `AssetDetail` has always reported it and
|
|
56
|
+
* nothing could write it; feature 068 needs it, because an imported image
|
|
57
|
+
* must keep the alternate text the source supplied, per language
|
|
58
|
+
* (FR-047). Not on `patchAssetRequestSchema`, so the HTTP surface is
|
|
59
|
+
* unchanged — this is a service-level field for module callers.
|
|
60
|
+
*/
|
|
61
|
+
altText?: Record<string, string> | null;
|
|
62
|
+
}): Promise<AssetDetail>;
|
|
63
|
+
setVisibility(assetId: string, visibility: 'public' | 'private'): Promise<AssetDetail>;
|
|
64
|
+
softDelete(assetId: string): Promise<{
|
|
65
|
+
deletedAt: Date;
|
|
66
|
+
purgeAfterAt: Date;
|
|
67
|
+
}>;
|
|
68
|
+
restore(assetId: string): Promise<AssetDetail>;
|
|
69
|
+
move(assetId: string, folderId: string | null): Promise<AssetDetail>;
|
|
70
|
+
moveMany(assetIds: string[], folderId: string | null): Promise<{
|
|
71
|
+
movedCount: number;
|
|
72
|
+
}>;
|
|
73
|
+
private summary;
|
|
74
|
+
private detail;
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=assets-library.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assets-library.service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/assets-library.service.ts"],"names":[],"mappings":"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"}
|