@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.
Files changed (139) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +61 -2
  3. package/dist/admin/api/assets-library-client.d.ts +29 -0
  4. package/dist/admin/api/assets-library-client.d.ts.map +1 -0
  5. package/dist/admin/api/assets-library-client.js +70 -0
  6. package/dist/admin/api/assets-library-client.js.map +1 -0
  7. package/dist/admin/components/AssetDetailDrawer.d.ts +8 -0
  8. package/dist/admin/components/AssetDetailDrawer.d.ts.map +1 -0
  9. package/dist/admin/components/AssetDetailDrawer.js +96 -0
  10. package/dist/admin/components/AssetDetailDrawer.js.map +1 -0
  11. package/dist/admin/components/FolderTree.d.ts +13 -0
  12. package/dist/admin/components/FolderTree.d.ts.map +1 -0
  13. package/dist/admin/components/FolderTree.js +71 -0
  14. package/dist/admin/components/FolderTree.js.map +1 -0
  15. package/dist/admin/index.d.ts +44 -0
  16. package/dist/admin/index.d.ts.map +1 -0
  17. package/dist/admin/index.js +46 -0
  18. package/dist/admin/index.js.map +1 -0
  19. package/dist/admin/pages/LibraryPage.d.ts +9 -0
  20. package/dist/admin/pages/LibraryPage.d.ts.map +1 -0
  21. package/dist/admin/pages/LibraryPage.js +163 -0
  22. package/dist/admin/pages/LibraryPage.js.map +1 -0
  23. package/dist/backend/entities/asset-folder.entity.d.ts +16 -0
  24. package/dist/backend/entities/asset-folder.entity.d.ts.map +1 -0
  25. package/dist/backend/entities/asset-folder.entity.js +57 -0
  26. package/dist/backend/entities/asset-folder.entity.js.map +1 -0
  27. package/dist/backend/entities/asset.entity.d.ts +38 -0
  28. package/dist/backend/entities/asset.entity.d.ts.map +1 -0
  29. package/dist/backend/entities/asset.entity.js +128 -0
  30. package/dist/backend/entities/asset.entity.js.map +1 -0
  31. package/dist/backend/index.d.ts +57 -0
  32. package/dist/backend/index.d.ts.map +1 -0
  33. package/dist/backend/index.js +150 -0
  34. package/dist/backend/index.js.map +1 -0
  35. package/dist/backend/jobs/hard-delete-asset.job.d.ts +18 -0
  36. package/dist/backend/jobs/hard-delete-asset.job.d.ts.map +1 -0
  37. package/dist/backend/jobs/hard-delete-asset.job.js +91 -0
  38. package/dist/backend/jobs/hard-delete-asset.job.js.map +1 -0
  39. package/dist/backend/plugin.d.ts +47 -0
  40. package/dist/backend/plugin.d.ts.map +1 -0
  41. package/dist/backend/plugin.js +96 -0
  42. package/dist/backend/plugin.js.map +1 -0
  43. package/dist/backend/routes.admin.d.ts +15 -0
  44. package/dist/backend/routes.admin.d.ts.map +1 -0
  45. package/dist/backend/routes.admin.js +189 -0
  46. package/dist/backend/routes.admin.js.map +1 -0
  47. package/dist/backend/routes.public.d.ts +14 -0
  48. package/dist/backend/routes.public.d.ts.map +1 -0
  49. package/dist/backend/routes.public.js +99 -0
  50. package/dist/backend/routes.public.js.map +1 -0
  51. package/dist/backend/services/asset-read-port.d.ts +103 -0
  52. package/dist/backend/services/asset-read-port.d.ts.map +1 -0
  53. package/dist/backend/services/asset-read-port.js +167 -0
  54. package/dist/backend/services/asset-read-port.js.map +1 -0
  55. package/dist/backend/services/assets-library.service.d.ts +76 -0
  56. package/dist/backend/services/assets-library.service.d.ts.map +1 -0
  57. package/dist/backend/services/assets-library.service.js +261 -0
  58. package/dist/backend/services/assets-library.service.js.map +1 -0
  59. package/dist/backend/services/cms-body-resolver.d.ts +6 -0
  60. package/dist/backend/services/cms-body-resolver.d.ts.map +1 -0
  61. package/dist/backend/services/cms-body-resolver.js +44 -0
  62. package/dist/backend/services/cms-body-resolver.js.map +1 -0
  63. package/dist/backend/services/folders.service.d.ts +29 -0
  64. package/dist/backend/services/folders.service.d.ts.map +1 -0
  65. package/dist/backend/services/folders.service.js +231 -0
  66. package/dist/backend/services/folders.service.js.map +1 -0
  67. package/dist/backend/services/hmac.d.ts +28 -0
  68. package/dist/backend/services/hmac.d.ts.map +1 -0
  69. package/dist/backend/services/hmac.js +50 -0
  70. package/dist/backend/services/hmac.js.map +1 -0
  71. package/dist/backend/services/reference-registry.d.ts +36 -0
  72. package/dist/backend/services/reference-registry.d.ts.map +1 -0
  73. package/dist/backend/services/reference-registry.js +63 -0
  74. package/dist/backend/services/reference-registry.js.map +1 -0
  75. package/dist/backend/services/storage/adapter-registry.d.ts +77 -0
  76. package/dist/backend/services/storage/adapter-registry.d.ts.map +1 -0
  77. package/dist/backend/services/storage/adapter-registry.js +95 -0
  78. package/dist/backend/services/storage/adapter-registry.js.map +1 -0
  79. package/dist/backend/services/storage/errors.d.ts +18 -0
  80. package/dist/backend/services/storage/errors.d.ts.map +1 -0
  81. package/dist/backend/services/storage/errors.js +30 -0
  82. package/dist/backend/services/storage/errors.js.map +1 -0
  83. package/dist/backend/services/storage/gcs-adapter.d.ts +42 -0
  84. package/dist/backend/services/storage/gcs-adapter.d.ts.map +1 -0
  85. package/dist/backend/services/storage/gcs-adapter.js +106 -0
  86. package/dist/backend/services/storage/gcs-adapter.js.map +1 -0
  87. package/dist/backend/services/storage/legacy-resolver.d.ts +15 -0
  88. package/dist/backend/services/storage/legacy-resolver.d.ts.map +1 -0
  89. package/dist/backend/services/storage/legacy-resolver.js +32 -0
  90. package/dist/backend/services/storage/legacy-resolver.js.map +1 -0
  91. package/dist/backend/services/storage/local-fs-adapter.d.ts +59 -0
  92. package/dist/backend/services/storage/local-fs-adapter.d.ts.map +1 -0
  93. package/dist/backend/services/storage/local-fs-adapter.js +153 -0
  94. package/dist/backend/services/storage/local-fs-adapter.js.map +1 -0
  95. package/dist/backend/services/storage/locator.d.ts +5 -0
  96. package/dist/backend/services/storage/locator.d.ts.map +1 -0
  97. package/dist/backend/services/storage/locator.js +16 -0
  98. package/dist/backend/services/storage/locator.js.map +1 -0
  99. package/dist/backend/services/storage/object-storage-port.d.ts +46 -0
  100. package/dist/backend/services/storage/object-storage-port.d.ts.map +1 -0
  101. package/dist/backend/services/storage/object-storage-port.js +78 -0
  102. package/dist/backend/services/storage/object-storage-port.js.map +1 -0
  103. package/dist/backend/services/storage/public-url-base.d.ts +50 -0
  104. package/dist/backend/services/storage/public-url-base.d.ts.map +1 -0
  105. package/dist/backend/services/storage/public-url-base.js +70 -0
  106. package/dist/backend/services/storage/public-url-base.js.map +1 -0
  107. package/dist/backend/services/storage/s3-adapter.d.ts +50 -0
  108. package/dist/backend/services/storage/s3-adapter.d.ts.map +1 -0
  109. package/dist/backend/services/storage/s3-adapter.js +110 -0
  110. package/dist/backend/services/storage/s3-adapter.js.map +1 -0
  111. package/dist/backend/services/storage/settings-view.d.ts +4 -0
  112. package/dist/backend/services/storage/settings-view.d.ts.map +1 -0
  113. package/dist/backend/services/storage/settings-view.js +73 -0
  114. package/dist/backend/services/storage/settings-view.js.map +1 -0
  115. package/dist/backend/services/storage/storage-adapter.d.ts +62 -0
  116. package/dist/backend/services/storage/storage-adapter.d.ts.map +1 -0
  117. package/dist/backend/services/storage/storage-adapter.js +10 -0
  118. package/dist/backend/services/storage/storage-adapter.js.map +1 -0
  119. package/dist/backend/services/upload-pipeline.d.ts +41 -0
  120. package/dist/backend/services/upload-pipeline.d.ts.map +1 -0
  121. package/dist/backend/services/upload-pipeline.js +231 -0
  122. package/dist/backend/services/upload-pipeline.js.map +1 -0
  123. package/dist/manifest.d.ts +185 -0
  124. package/dist/manifest.d.ts.map +1 -0
  125. package/dist/manifest.js +229 -0
  126. package/dist/manifest.js.map +1 -0
  127. package/dist/migrations/20260505T102206_assets_library_init.d.ts +35 -0
  128. package/dist/migrations/20260505T102206_assets_library_init.d.ts.map +1 -0
  129. package/dist/migrations/20260505T102206_assets_library_init.js +132 -0
  130. package/dist/migrations/20260505T102206_assets_library_init.js.map +1 -0
  131. package/dist/migrations/index.d.ts +27 -0
  132. package/dist/migrations/index.d.ts.map +1 -0
  133. package/dist/migrations/index.js +29 -0
  134. package/dist/migrations/index.js.map +1 -0
  135. package/docs/assets-library/index.md +125 -0
  136. package/i18n/en.json +54 -0
  137. package/i18n/pl.json +54 -0
  138. package/package.json +99 -3
  139. package/tailwind.css +14 -0
@@ -0,0 +1,163 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ // Library page — feature 013 / US2 / T069.
3
+ // Three-pane Magento-2-Media-Gallery–style layout: folder tree + asset grid
4
+ // + per-asset detail drawer. Inline upload affordance per current folder.
5
+ import { useCallback, useEffect, useRef, useState } from 'react';
6
+ import { Alert, AlertDescription, Button, Card, CardContent, CardHeader, CardTitle, Input, PageHeader } from '@endora-commerce/admin-kit/ui';
7
+ import { useTranslation } from '@endora-commerce/admin-kit/i18n';
8
+ import { AssetUploader } from '@endora-commerce/admin-kit/components';
9
+ import { toAbsoluteAssetUrl } from '@endora-commerce/admin-kit/lib';
10
+ import { FolderTree } from '../components/FolderTree.js';
11
+ import { AssetDetailDrawer } from '../components/AssetDetailDrawer.js';
12
+ import { assetsLibraryClient, } from '../api/assets-library-client.js';
13
+ export function LibraryPage() {
14
+ const t = useTranslation('assets_library');
15
+ const [folders, setFolders] = useState([]);
16
+ const [folderId, setFolderId] = useState(null); // null = Unsorted (root)
17
+ const [items, setItems] = useState([]);
18
+ const [q, setQ] = useState('');
19
+ const [debouncedQ, setDebouncedQ] = useState('');
20
+ const [cursor, setCursor] = useState(null);
21
+ const [hasMore, setHasMore] = useState(false);
22
+ const [error, setError] = useState(null);
23
+ const [info, setInfo] = useState(null);
24
+ const [loading, setLoading] = useState(true);
25
+ const [loadingMore, setLoadingMore] = useState(false);
26
+ const [selected, setSelected] = useState(null);
27
+ const PAGE_SIZE = 60;
28
+ const loadFolders = useCallback(async () => {
29
+ try {
30
+ setFolders(await assetsLibraryClient.listFolders());
31
+ }
32
+ catch (e) {
33
+ setError(e instanceof Error ? e.message : String(e));
34
+ }
35
+ }, []);
36
+ // Debounce the search box so each keystroke does not fire a request; the
37
+ // actual filtering is done server-side (see loadFirstPage), so the search
38
+ // covers every asset in the folder, not only the ones already loaded.
39
+ useEffect(() => {
40
+ const h = setTimeout(() => setDebouncedQ(q), 300);
41
+ return () => clearTimeout(h);
42
+ }, [q]);
43
+ // First page — replaces the list. Runs on folder change or a new search.
44
+ const loadFirstPage = useCallback(async () => {
45
+ setLoading(true);
46
+ setError(null);
47
+ try {
48
+ const out = await assetsLibraryClient.listAssets({
49
+ folderId,
50
+ ...(debouncedQ ? { q: debouncedQ } : {}),
51
+ limit: PAGE_SIZE,
52
+ });
53
+ setItems(out.data);
54
+ setCursor(out.nextCursor);
55
+ setHasMore(out.nextCursor !== null);
56
+ }
57
+ catch (e) {
58
+ setError(e instanceof Error ? e.message : String(e));
59
+ }
60
+ finally {
61
+ setLoading(false);
62
+ }
63
+ }, [folderId, debouncedQ]);
64
+ // Next page — appends, keyed off the server cursor.
65
+ const loadMore = useCallback(async () => {
66
+ if (!cursor || loadingMore)
67
+ return;
68
+ setLoadingMore(true);
69
+ setError(null);
70
+ try {
71
+ const out = await assetsLibraryClient.listAssets({
72
+ folderId,
73
+ ...(debouncedQ ? { q: debouncedQ } : {}),
74
+ cursor,
75
+ limit: PAGE_SIZE,
76
+ });
77
+ setItems((prev) => [...prev, ...out.data]);
78
+ setCursor(out.nextCursor);
79
+ setHasMore(out.nextCursor !== null);
80
+ }
81
+ catch (e) {
82
+ setError(e instanceof Error ? e.message : String(e));
83
+ }
84
+ finally {
85
+ setLoadingMore(false);
86
+ }
87
+ }, [folderId, debouncedQ, cursor, loadingMore]);
88
+ useEffect(() => {
89
+ void loadFolders();
90
+ }, [loadFolders]);
91
+ useEffect(() => {
92
+ void loadFirstPage();
93
+ }, [loadFirstPage]);
94
+ // Infinite scroll — auto-load the next page when the sentinel scrolls into
95
+ // view. The "Load more" button remains as an explicit fallback.
96
+ const sentinelRef = useRef(null);
97
+ useEffect(() => {
98
+ const node = sentinelRef.current;
99
+ if (!node || !hasMore)
100
+ return undefined;
101
+ const observer = new IntersectionObserver((entries) => {
102
+ if (entries[0]?.isIntersecting)
103
+ void loadMore();
104
+ });
105
+ observer.observe(node);
106
+ return () => observer.disconnect();
107
+ }, [hasMore, loadMore]);
108
+ // Backwards-compatible alias — child callbacks call loadItems() to refresh.
109
+ const loadItems = loadFirstPage;
110
+ const onCreateFolder = async (parentId, name) => {
111
+ try {
112
+ await assetsLibraryClient.createFolder({ parentId, name });
113
+ await loadFolders();
114
+ }
115
+ catch (e) {
116
+ setError(e instanceof Error ? e.message : String(e));
117
+ }
118
+ };
119
+ const onRenameFolder = async (id, name) => {
120
+ try {
121
+ await assetsLibraryClient.patchFolder(id, { name });
122
+ await loadFolders();
123
+ }
124
+ catch (e) {
125
+ setError(e instanceof Error ? e.message : String(e));
126
+ }
127
+ };
128
+ const onDeleteFolder = async (id) => {
129
+ try {
130
+ const choice = window.confirm(t('folders.deleteConfirm'));
131
+ if (!choice)
132
+ return;
133
+ const out = await assetsLibraryClient.deleteFolder(id, {
134
+ ifNonEmpty: 'moveContentsToParent',
135
+ });
136
+ setInfo(t('folders.removed', { id: out.deletedFolderId }));
137
+ if (folderId === id)
138
+ setFolderId(null);
139
+ await loadFolders();
140
+ await loadItems();
141
+ }
142
+ catch (e) {
143
+ setError(e instanceof Error ? e.message : String(e));
144
+ }
145
+ };
146
+ return (_jsxs("div", { className: "space-y-4", children: [_jsx(PageHeader, { title: t('page.title'), description: t('page.description') }), error ? (_jsx(Alert, { variant: "destructive", children: _jsx(AlertDescription, { children: error }) })) : null, info ? (_jsx(Alert, { children: _jsx(AlertDescription, { children: info }) })) : null, _jsxs("div", { className: "grid grid-cols-12 gap-4", children: [_jsxs(Card, { className: "col-span-3", children: [_jsx(CardHeader, { children: _jsx(CardTitle, { className: "text-base", children: t('folders.title') }) }), _jsx(CardContent, { children: _jsx(FolderTree, { folders: folders, selectedId: folderId, onSelect: setFolderId, onCreate: onCreateFolder, onRename: onRenameFolder, onDelete: onDeleteFolder }) })] }), _jsxs(Card, { className: selected ? 'col-span-6' : 'col-span-9', children: [_jsxs(CardHeader, { className: "flex flex-row items-center justify-between gap-2", children: [_jsx(CardTitle, { className: "text-base", children: t('assets.title') }), _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Input, { value: q, onChange: (e) => setQ(e.target.value), onKeyDown: (e) => {
147
+ if (e.key === 'Enter')
148
+ setDebouncedQ(q);
149
+ }, placeholder: t('assets.searchPlaceholder'), className: "w-64" }), _jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: () => setDebouncedQ(q), children: t('common.search') })] })] }), _jsxs(CardContent, { className: "space-y-4", children: [_jsx(AssetUploader, { defaults: { folderId }, triggerLabel: t('uploader.triggerCurrentFolder'), onUploaded: () => {
150
+ void loadItems();
151
+ } }), loading ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('common.loading') })) : items.length === 0 ? (_jsx("p", { className: "text-sm text-muted-foreground", children: t('assets.emptyFolder') })) : (_jsx("div", { className: "grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5", children: items.map((a) => (_jsxs("button", { type: "button", className: `group overflow-hidden rounded-md border bg-muted/30 p-2 text-left transition hover:border-primary ${selected === a.id ? 'border-primary ring-2 ring-primary/30' : ''}`, onClick: () => setSelected(a.id), children: [a.mimeType.startsWith('image/') ? (
152
+ // eslint-disable-next-line jsx-a11y/alt-text
153
+ _jsx("img", { src: toAbsoluteAssetUrl(a.url), loading: "lazy", className: "aspect-square w-full rounded object-cover" })) : (_jsx("div", { className: "flex aspect-square w-full items-center justify-center rounded bg-muted text-xs text-muted-foreground", children: a.mimeType })), _jsx("div", { className: "mt-1 truncate text-xs", children: a.label ?? a.filename }), _jsxs("div", { className: "truncate text-[10px] text-muted-foreground", children: [a.visibility, " \u00B7 ", Number(a.sizeBytes), "B"] })] }, a.id))) })), !loading && hasMore ? (_jsx("div", { ref: sentinelRef, className: "flex justify-center pt-2", children: _jsx(Button, { type: "button", variant: "outline", size: "sm", disabled: loadingMore, onClick: () => void loadMore(), children: loadingMore ? t('common.loading') : t('assets.loadMore') }) })) : null] })] }), selected ? (_jsx("div", { className: "col-span-3", children: _jsx(AssetDetailDrawer, { assetId: selected, onChanged: () => {
154
+ void loadItems();
155
+ }, onClose: () => setSelected(null) }) })) : null] })] }));
156
+ }
157
+ /**
158
+ * The registry loads a route component through a dynamic-import factory and
159
+ * reads its default export (feature 091, FR-013). The named export stays: it is
160
+ * the spelling this module's own code and its tests use.
161
+ */
162
+ export default LibraryPage;
163
+ //# sourceMappingURL=LibraryPage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LibraryPage.js","sourceRoot":"","sources":["../../../src/admin/pages/LibraryPage.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * AssetFolder — organisational tree node for the Assets Library page.
4
+ * Folders are pure metadata; moving an asset between folders is a metadata
5
+ * update only, never a physical file move (research R11, FR-008).
6
+ */
7
+ export declare class AssetFolder {
8
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'parentId' | 'position';
9
+ id: string;
10
+ parentId?: string | null;
11
+ name: string;
12
+ position: number;
13
+ createdAt: Date;
14
+ updatedAt: Date;
15
+ }
16
+ //# sourceMappingURL=asset-folder.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-folder.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/asset-folder.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;GAIG;AACH,qBAEa,WAAW;IACtB,CAAC,aAAa,CAAC,CAAC,EAAE,IAAI,GAAG,WAAW,GAAG,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;IAG7E,EAAE,EAAE,MAAM,CAAgB;IAI1B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGzB,IAAI,EAAG,MAAM,CAAC;IAGd,QAAQ,EAAE,MAAM,CAAK;IAGrB,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;CAC9B"}
@@ -0,0 +1,57 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * AssetFolder — organisational tree node for the Assets Library page.
15
+ * Folders are pure metadata; moving an asset between folders is a metadata
16
+ * update only, never a physical file move (research R11, FR-008).
17
+ */
18
+ let AssetFolder = class AssetFolder {
19
+ [OptionalProps];
20
+ id = randomUUID();
21
+ parentId;
22
+ name;
23
+ position = 0;
24
+ createdAt = new Date();
25
+ updatedAt = new Date();
26
+ };
27
+ __decorate([
28
+ PrimaryKey({ type: 'uuid' }),
29
+ __metadata("design:type", String)
30
+ ], AssetFolder.prototype, "id", void 0);
31
+ __decorate([
32
+ Property({ type: 'uuid', nullable: true }),
33
+ Index(),
34
+ __metadata("design:type", Object)
35
+ ], AssetFolder.prototype, "parentId", void 0);
36
+ __decorate([
37
+ Property({ type: 'string', length: 160 }),
38
+ __metadata("design:type", String)
39
+ ], AssetFolder.prototype, "name", void 0);
40
+ __decorate([
41
+ Property({ type: 'integer' }),
42
+ __metadata("design:type", Number)
43
+ ], AssetFolder.prototype, "position", void 0);
44
+ __decorate([
45
+ Property({ type: 'datetime', onCreate: () => new Date() }),
46
+ __metadata("design:type", Date)
47
+ ], AssetFolder.prototype, "createdAt", void 0);
48
+ __decorate([
49
+ Property({ type: 'datetime', onUpdate: () => new Date() }),
50
+ __metadata("design:type", Date)
51
+ ], AssetFolder.prototype, "updatedAt", void 0);
52
+ AssetFolder = __decorate([
53
+ GlobalEntity(),
54
+ Entity({ tableName: 'asset_folders' })
55
+ ], AssetFolder);
56
+ export { AssetFolder };
57
+ //# sourceMappingURL=asset-folder.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset-folder.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/asset-folder.entity.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACrF,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC;;;;GAIG;AAGI,IAAM,WAAW,GAAjB,MAAM,WAAW;IACtB,CAAC,aAAa,CAAC,CAA8D;IAG7E,EAAE,GAAW,UAAU,EAAE,CAAC;IAI1B,QAAQ,CAAiB;IAGzB,IAAI,CAAU;IAGd,QAAQ,GAAW,CAAC,CAAC;IAGrB,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;IAG7B,SAAS,GAAS,IAAI,IAAI,EAAE,CAAC;CAC9B,CAAA;AAjBC;IADC,UAAU,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;uCACH;AAI1B;IAFC,QAAQ,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,KAAK,EAAE;;6CACiB;AAGzB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;;yCAC5B;AAGd;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;6CACT;AAGrB;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;8CAAc;AAG7B;IADC,QAAQ,CAAC,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;8BAChD,IAAI;8CAAc;AApBlB,WAAW;IAFvB,YAAY,EAAE;IACd,MAAM,CAAC,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;GAC1B,WAAW,CAqBvB"}
@@ -0,0 +1,38 @@
1
+ import { OptionalProps } from '@mikro-orm/core';
2
+ /**
3
+ * Asset — file managed by the Assets Library (feature 013). Replaces the
4
+ * pre-013 `assets` module entity. Existing FK references from Catalog
5
+ * (gallery_items.asset_id, product_attachments.asset_id, products.download_asset_id)
6
+ * and the new categories.main_image_asset_id continue to point here.
7
+ *
8
+ * Visibility, storage backend, and folder are introduced in feature 013;
9
+ * `storageUrl` is retained for one release as a read-only legacy escape hatch
10
+ * and is no longer written by new code (research R11 / FR-034).
11
+ */
12
+ export declare class Asset {
13
+ [OptionalProps]?: 'id' | 'createdAt' | 'updatedAt' | 'altText' | 'deletedAt' | 'folderId' | 'visibility' | 'label' | 'storageBackend' | 'storageLocator' | 'pendingCleanup' | 'purgeAfterAt' | 'mimeTypeOverridden';
14
+ id: string;
15
+ kind: 'image' | 'video' | 'pdf' | 'certificate' | 'other';
16
+ filename: string;
17
+ mimeType: string;
18
+ sizeBytes: string;
19
+ /**
20
+ * @deprecated Use `storageLocator` + `storageBackend` instead. Retained
21
+ * for one release for the legacy-decomp escape hatch (research R11);
22
+ * removed in a follow-up cleanup PR.
23
+ */
24
+ storageUrl: string;
25
+ altText?: Record<string, string> | null;
26
+ folderId?: string | null;
27
+ visibility: 'public' | 'private';
28
+ label?: string | null;
29
+ storageBackend: 'local' | 's3' | 'gcs' | 'legacy';
30
+ storageLocator: string;
31
+ pendingCleanup: boolean;
32
+ purgeAfterAt?: Date | null;
33
+ mimeTypeOverridden: boolean;
34
+ createdAt: Date;
35
+ updatedAt: Date;
36
+ deletedAt?: Date | null;
37
+ }
38
+ //# sourceMappingURL=asset.entity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset.entity.d.ts","sourceRoot":"","sources":["../../../src/backend/entities/asset.entity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,aAAa,EAAwB,MAAM,iBAAiB,CAAC;AAIrF;;;;;;;;;GASG;AACH,qBAEa,KAAK;IAChB,CAAC,aAAa,CAAC,CAAC,EACZ,IAAI,GACJ,WAAW,GACX,WAAW,GACX,SAAS,GACT,WAAW,GACX,UAAU,GACV,YAAY,GACZ,OAAO,GACP,gBAAgB,GAChB,gBAAgB,GAChB,gBAAgB,GAChB,cAAc,GACd,oBAAoB,CAAC;IAGzB,EAAE,EAAE,MAAM,CAAgB;IAI1B,IAAI,EAAG,OAAO,GAAG,OAAO,GAAG,KAAK,GAAG,aAAa,GAAG,OAAO,CAAC;IAG3D,QAAQ,EAAG,MAAM,CAAC;IAGlB,QAAQ,EAAG,MAAM,CAAC;IAGlB,SAAS,EAAG,MAAM,CAAC;IAEnB;;;;OAIG;IAEH,UAAU,EAAG,MAAM,CAAC;IAGpB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IAIxC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGzB,UAAU,EAAE,QAAQ,GAAG,SAAS,CAAY;IAG5C,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAGtB,cAAc,EAAE,OAAO,GAAG,IAAI,GAAG,KAAK,GAAG,QAAQ,CAAW;IAG5D,cAAc,EAAE,MAAM,CAAM;IAG5B,cAAc,EAAE,OAAO,CAAS;IAGhC,YAAY,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IAG3B,kBAAkB,EAAE,OAAO,CAAS;IAGpC,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,EAAE,IAAI,CAAc;IAG7B,SAAS,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;CACzB"}
@@ -0,0 +1,128 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Entity, Index, OptionalProps, PrimaryKey, Property } from '@mikro-orm/core';
11
+ import { GlobalEntity } from '@endora-commerce/platform/tenancy';
12
+ import { randomUUID } from 'crypto';
13
+ /**
14
+ * Asset — file managed by the Assets Library (feature 013). Replaces the
15
+ * pre-013 `assets` module entity. Existing FK references from Catalog
16
+ * (gallery_items.asset_id, product_attachments.asset_id, products.download_asset_id)
17
+ * and the new categories.main_image_asset_id continue to point here.
18
+ *
19
+ * Visibility, storage backend, and folder are introduced in feature 013;
20
+ * `storageUrl` is retained for one release as a read-only legacy escape hatch
21
+ * and is no longer written by new code (research R11 / FR-034).
22
+ */
23
+ let Asset = class Asset {
24
+ [OptionalProps];
25
+ id = randomUUID();
26
+ kind;
27
+ filename;
28
+ mimeType;
29
+ sizeBytes;
30
+ /**
31
+ * @deprecated Use `storageLocator` + `storageBackend` instead. Retained
32
+ * for one release for the legacy-decomp escape hatch (research R11);
33
+ * removed in a follow-up cleanup PR.
34
+ */
35
+ storageUrl;
36
+ altText;
37
+ folderId;
38
+ visibility = 'public';
39
+ label;
40
+ storageBackend = 'local';
41
+ storageLocator = '';
42
+ pendingCleanup = false;
43
+ purgeAfterAt;
44
+ mimeTypeOverridden = false;
45
+ createdAt = new Date();
46
+ updatedAt = new Date();
47
+ deletedAt;
48
+ };
49
+ __decorate([
50
+ PrimaryKey({ type: 'uuid' }),
51
+ __metadata("design:type", String)
52
+ ], Asset.prototype, "id", void 0);
53
+ __decorate([
54
+ Property({ type: 'string', length: 16 }),
55
+ Index(),
56
+ __metadata("design:type", String)
57
+ ], Asset.prototype, "kind", void 0);
58
+ __decorate([
59
+ Property({ type: 'string', length: 255 }),
60
+ __metadata("design:type", String)
61
+ ], Asset.prototype, "filename", void 0);
62
+ __decorate([
63
+ Property({ type: 'string', length: 127 }),
64
+ __metadata("design:type", String)
65
+ ], Asset.prototype, "mimeType", void 0);
66
+ __decorate([
67
+ Property({ type: 'bigint' }),
68
+ __metadata("design:type", String)
69
+ ], Asset.prototype, "sizeBytes", void 0);
70
+ __decorate([
71
+ Property({ type: 'string', length: 2048 }),
72
+ __metadata("design:type", String)
73
+ ], Asset.prototype, "storageUrl", void 0);
74
+ __decorate([
75
+ Property({ type: 'json', nullable: true }),
76
+ __metadata("design:type", Object)
77
+ ], Asset.prototype, "altText", void 0);
78
+ __decorate([
79
+ Property({ type: 'uuid', nullable: true }),
80
+ Index(),
81
+ __metadata("design:type", Object)
82
+ ], Asset.prototype, "folderId", void 0);
83
+ __decorate([
84
+ Property({ type: 'string', length: 7 }),
85
+ __metadata("design:type", String)
86
+ ], Asset.prototype, "visibility", void 0);
87
+ __decorate([
88
+ Property({ type: 'text', nullable: true }),
89
+ __metadata("design:type", Object)
90
+ ], Asset.prototype, "label", void 0);
91
+ __decorate([
92
+ Property({ type: 'string', length: 8 }),
93
+ __metadata("design:type", String)
94
+ ], Asset.prototype, "storageBackend", void 0);
95
+ __decorate([
96
+ Property({ type: 'string', length: 2048 }),
97
+ __metadata("design:type", String)
98
+ ], Asset.prototype, "storageLocator", void 0);
99
+ __decorate([
100
+ Property({ type: 'boolean' }),
101
+ __metadata("design:type", Boolean)
102
+ ], Asset.prototype, "pendingCleanup", void 0);
103
+ __decorate([
104
+ Property({ type: 'datetime', nullable: true }),
105
+ __metadata("design:type", Object)
106
+ ], Asset.prototype, "purgeAfterAt", void 0);
107
+ __decorate([
108
+ Property({ type: 'boolean' }),
109
+ __metadata("design:type", Boolean)
110
+ ], Asset.prototype, "mimeTypeOverridden", void 0);
111
+ __decorate([
112
+ Property({ type: 'datetime', onCreate: () => new Date() }),
113
+ __metadata("design:type", Date)
114
+ ], Asset.prototype, "createdAt", void 0);
115
+ __decorate([
116
+ Property({ type: 'datetime', onUpdate: () => new Date() }),
117
+ __metadata("design:type", Date)
118
+ ], Asset.prototype, "updatedAt", void 0);
119
+ __decorate([
120
+ Property({ type: 'datetime', nullable: true }),
121
+ __metadata("design:type", Object)
122
+ ], Asset.prototype, "deletedAt", void 0);
123
+ Asset = __decorate([
124
+ GlobalEntity(),
125
+ Entity({ tableName: 'assets' })
126
+ ], Asset);
127
+ export { Asset };
128
+ //# sourceMappingURL=asset.entity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"asset.entity.js","sourceRoot":"","sources":["../../../src/backend/entities/asset.entity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { AuditPort } from '@endora-commerce/platform/kernel';
3
+ import type { ModuleContext } from '@endora-commerce/platform/kernel';
4
+ import type { RequireAdminFactory } from '@endora-commerce/platform/kernel';
5
+ import { assetsLibraryModule } from './plugin.js';
6
+ import { AssetFolder } from './entities/asset-folder.entity.js';
7
+ import { Asset } from './entities/asset.entity.js';
8
+ /**
9
+ * `assets_library` — the module whose permission gate defaulted to open
10
+ * (feature 072, wave 1, T092).
11
+ *
12
+ * The conversion is otherwise unremarkable: one construction site per root, one
13
+ * plugin, a registry three other modules register their reference resolvers
14
+ * into. What is worth stopping on is the option shape it had:
15
+ *
16
+ * // Permission gate factory. When omitted, a permissive no-op is used.
17
+ * requireAdmin?: RequireAdminFactory;
18
+ *
19
+ * Both roots do pass one, so nothing was open in production. But a **security
20
+ * gate that defaults to permissive** is the class of latent defect this wave has
21
+ * now removed three times over — `addresses`' unvalidated writes,
22
+ * `customer_accounts`' MFA-less auth service, `orders`' unarmed address service.
23
+ * An optional argument whose omission is silent, whose default is the unsafe
24
+ * direction, and which no test notices because the safe path is the one
25
+ * exercised. Resolving `requireAdmin` from the container removes the option
26
+ * entirely: there is no omission left to be silent about.
27
+ *
28
+ * **One registration holds the whole module result**, plugin and handle
29
+ * together. Registering them separately would mean two `assetsLibraryModule`
30
+ * calls per composition — the routes serving one `AssetsLibraryService` and one
31
+ * `AssetReferenceRegistry` while `catalog`, `cms` and `megamenu` registered
32
+ * their resolvers into a different pair. That is exactly the multi-instance
33
+ * defect this wave keeps removing, and it is easy to write by accident here,
34
+ * because the factory returns two things that look independent.
35
+ */
36
+ type AssetsLibraryResult = ReturnType<typeof assetsLibraryModule>;
37
+ export interface AssetsLibraryCradle {
38
+ readonly emFactory: () => EntityManager;
39
+ readonly auditLogService: AuditPort;
40
+ readonly requireAdmin: RequireAdminFactory;
41
+ readonly assetsLibrary: AssetsLibraryResult;
42
+ }
43
+ export declare function registerModule(ctx: ModuleContext): void;
44
+ /**
45
+ * The module's persisted entity classes, on the `./backend` subpath, as one
46
+ * array and **no named class export** (D-168).
47
+ *
48
+ * This is the shape the platform reads when the package is *installed*: the
49
+ * boot-time loader (`src/packages/package-runtime.ts`, `exported['entities']`)
50
+ * and the static declaration reader (`scripts/lib/package-declarations.ts`),
51
+ * which is the third source of `check:module-boundary`'s `table→owner` map and
52
+ * the package pass of `check-entity-tenant-classification`. A missing array is
53
+ * answered with `[]` — zero entities registered, no error anywhere.
54
+ */
55
+ export declare const entities: (typeof Asset | typeof AssetFolder)[];
56
+ export {};
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/backend/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAM3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAElE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kCAAkC,CAAC;AACtE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD,OAAO,EAAE,WAAW,EAAE,MAAM,mCAAmC,CAAC;AAChE,OAAO,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAEnD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,KAAK,mBAAmB,GAAG,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAElE,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,SAAS,EAAE,MAAM,aAAa,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,YAAY,EAAE,mBAAmB,CAAC;IAC3C,QAAQ,CAAC,aAAa,EAAE,mBAAmB,CAAC;CAC7C;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,GAAG,IAAI,CAsJvD;AAED;;;;;;;;;;GAUG;AACH,eAAO,MAAM,QAAQ,uCAGpB,CAAC"}