@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,261 @@
1
+ // AssetsLibraryService — public facade. US1 fills upload / get / list /
2
+ // patch / setVisibility / resolveUrl. US2 will fill softDelete / restore /
3
+ // move. US3 brings cloud adapters online.
4
+ import { ERROR_CODES } from '@endora-commerce/contracts';
5
+ import { Asset } from '../entities/asset.entity.js';
6
+ import { HttpError } from '@endora-commerce/platform/http';
7
+ import { UploadPipeline } from './upload-pipeline.js';
8
+ import { LegacyAssetCannotHardenError } from './storage/errors.js';
9
+ import { recordAuditFromContext } from '@endora-commerce/platform/commands';
10
+ export class NotImplementedYet extends Error {
11
+ name = 'NotImplementedYet';
12
+ constructor(method) {
13
+ super(`AssetsLibraryService.${method} is not implemented in this build (later phase / user story).`);
14
+ }
15
+ }
16
+ export class AssetsLibraryService {
17
+ deps;
18
+ pipeline;
19
+ constructor(deps) {
20
+ this.deps = deps;
21
+ this.pipeline = new UploadPipeline({
22
+ emFactory: deps.emFactory,
23
+ adapters: deps.adapters,
24
+ loadPolicy: deps.loadUploadPolicy,
25
+ ...(deps.auditLog ? { auditLog: deps.auditLog } : {}),
26
+ });
27
+ }
28
+ #audit(em, action, objectId, stateBefore, stateAfter) {
29
+ if (this.deps.auditLog) {
30
+ recordAuditFromContext(this.deps.auditLog, em, {
31
+ action,
32
+ objectType: 'asset',
33
+ objectId,
34
+ stateBefore,
35
+ stateAfter,
36
+ });
37
+ }
38
+ }
39
+ /** Upload entry point — runs the atomic put + insert + compensating-delete pipeline. */
40
+ async upload(input) {
41
+ const asset = await this.pipeline.run(input);
42
+ return this.detail(asset);
43
+ }
44
+ /** Resolve the serving URL for an asset by id (public or private). */
45
+ async resolveUrl(assetId, opts = {}) {
46
+ const em = this.deps.emFactory();
47
+ const a = await em.findOne(Asset, { id: assetId });
48
+ if (!a)
49
+ throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, `Asset ${assetId} not found.`);
50
+ const adapter = await this.deps.adapters.getForBackend(a.storageBackend);
51
+ return adapter.resolveUrl({
52
+ locator: a.storageLocator || a.storageUrl,
53
+ visibility: a.visibility,
54
+ ...(opts.ttlSec !== undefined ? { ttlSec: opts.ttlSec } : {}),
55
+ });
56
+ }
57
+ async getAsset(assetId) {
58
+ const em = this.deps.emFactory();
59
+ const a = await em.findOne(Asset, { id: assetId });
60
+ if (!a)
61
+ throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, `Asset ${assetId} not found.`);
62
+ return this.detail(a);
63
+ }
64
+ async listAssets(query) {
65
+ const em = this.deps.emFactory();
66
+ const limit = Math.min(Math.max(query.limit ?? 50, 1), 100);
67
+ // Build the predicate as an $and of independent clauses so the search OR
68
+ // (filename/label) does not collide with any other clause on a single
69
+ // top-level `$or` key.
70
+ const clauses = [];
71
+ if (query.folderId !== undefined)
72
+ clauses.push({ folderId: query.folderId });
73
+ if (query.visibility)
74
+ clauses.push({ visibility: query.visibility });
75
+ if (query.mime)
76
+ clauses.push({ mimeType: { $like: `${query.mime}%` } });
77
+ if (query.q) {
78
+ clauses.push({
79
+ $or: [
80
+ { filename: { $ilike: `%${query.q}%` } },
81
+ { label: { $ilike: `%${query.q}%` } },
82
+ ],
83
+ });
84
+ }
85
+ if (!query.includeDeleted)
86
+ clauses.push({ deletedAt: null });
87
+ const where = clauses.length > 0 ? { $and: clauses } : {};
88
+ // Offset-based pagination. The opaque cursor carries the next offset.
89
+ // Keyset pagination is not usable here: `createdAt` is stored with
90
+ // microsecond precision but a JS Date (and the ISO cursor) only carries
91
+ // milliseconds, so a keyset boundary on (createdAt, id) silently drops the
92
+ // rows that share a truncated instant. Offset over a total order
93
+ // (createdAt DESC, id DESC) is precision-independent and correct.
94
+ const offset = query.cursor ? (decodeCursor(query.cursor) ?? 0) : 0;
95
+ const rows = await em.find(Asset, where, {
96
+ orderBy: { createdAt: 'desc', id: 'desc' },
97
+ offset,
98
+ limit: limit + 1,
99
+ });
100
+ const overflow = rows.length > limit;
101
+ const page = overflow ? rows.slice(0, limit) : rows;
102
+ const nextCursor = overflow ? encodeCursor(offset + limit) : null;
103
+ const summaries = await Promise.all(page.map((a) => this.summary(a)));
104
+ return { data: summaries, nextCursor };
105
+ }
106
+ async patchAsset(assetId, patch) {
107
+ const em = this.deps.emFactory();
108
+ const a = await em.findOne(Asset, { id: assetId });
109
+ if (!a)
110
+ throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, `Asset ${assetId} not found.`);
111
+ if (patch.filename !== undefined)
112
+ a.filename = patch.filename;
113
+ if (patch.label !== undefined)
114
+ a.label = patch.label;
115
+ if (patch.altText !== undefined)
116
+ a.altText = patch.altText;
117
+ if (patch.mimeType !== undefined) {
118
+ a.mimeType = patch.mimeType;
119
+ a.mimeTypeOverridden = true;
120
+ }
121
+ if (patch.folderId !== undefined)
122
+ a.folderId = patch.folderId;
123
+ if (patch.visibility !== undefined && patch.visibility !== a.visibility) {
124
+ // Refuse to flip a `legacy` asset to private — we cannot sign URLs we
125
+ // didn't issue.
126
+ if (a.storageBackend === 'legacy' && patch.visibility === 'private') {
127
+ throw new HttpError(409, ERROR_CODES.ASSET_LEGACY_LOCATOR_CANNOT_HARDEN, 'Cannot mark a `legacy` asset as private — re-upload it through the active adapter first.');
128
+ }
129
+ const adapter = await this.deps.adapters.getForBackend(a.storageBackend);
130
+ // Cloud adapters update object ACLs; local FS no-ops (visibility is
131
+ // enforced by routes.public.ts on every request).
132
+ if ('setVisibility' in adapter && typeof adapter.setVisibility === 'function') {
133
+ try {
134
+ await adapter.setVisibility({ locator: a.storageLocator || a.storageUrl, visibility: patch.visibility });
135
+ }
136
+ catch (err) {
137
+ if (err instanceof LegacyAssetCannotHardenError) {
138
+ throw new HttpError(409, ERROR_CODES.ASSET_LEGACY_LOCATOR_CANNOT_HARDEN, err.message);
139
+ }
140
+ throw err;
141
+ }
142
+ }
143
+ a.visibility = patch.visibility;
144
+ }
145
+ this.#audit(em, 'asset.update', a.id, null, { filename: a.filename, visibility: a.visibility });
146
+ await em.flush();
147
+ return this.detail(a);
148
+ }
149
+ async setVisibility(assetId, visibility) {
150
+ return this.patchAsset(assetId, { visibility });
151
+ }
152
+ // — US2 — soft-delete / restore / move ------------------------------------
153
+ async softDelete(assetId) {
154
+ const em = this.deps.emFactory();
155
+ const a = await em.findOne(Asset, { id: assetId });
156
+ if (!a)
157
+ throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, `Asset ${assetId} not found.`);
158
+ if (a.deletedAt) {
159
+ // Idempotent — return current state.
160
+ return { deletedAt: a.deletedAt, purgeAfterAt: a.purgeAfterAt };
161
+ }
162
+ // Reference protection (FR-030).
163
+ const refs = await this.deps.referenceRegistry.findReferences(assetId);
164
+ if (refs.length > 0) {
165
+ throw new HttpError(409, ERROR_CODES.ASSET_REFERENCED, `Asset is in use by ${refs.length} record(s); detach those first.`, refs.slice(0, 20).map((r) => ({
166
+ path: r.kind,
167
+ issue: r.label,
168
+ })));
169
+ }
170
+ const retentionDays = 30; // assets.soft_delete_retention_days; reads inline in US2.
171
+ const now = new Date();
172
+ a.deletedAt = now;
173
+ a.purgeAfterAt = new Date(now.getTime() + retentionDays * 24 * 60 * 60 * 1000);
174
+ this.#audit(em, 'asset.soft_delete', a.id, { filename: a.filename }, null);
175
+ await em.flush();
176
+ return { deletedAt: a.deletedAt, purgeAfterAt: a.purgeAfterAt };
177
+ }
178
+ async restore(assetId) {
179
+ const em = this.deps.emFactory();
180
+ const a = await em.findOne(Asset, { id: assetId });
181
+ if (!a)
182
+ throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, `Asset ${assetId} not found.`);
183
+ a.deletedAt = null;
184
+ a.purgeAfterAt = null;
185
+ a.pendingCleanup = false;
186
+ this.#audit(em, 'asset.restore', a.id, null, { filename: a.filename });
187
+ await em.flush();
188
+ return this.detail(a);
189
+ }
190
+ async move(assetId, folderId) {
191
+ const em = this.deps.emFactory();
192
+ const a = await em.findOne(Asset, { id: assetId });
193
+ if (!a)
194
+ throw new HttpError(404, ERROR_CODES.ASSET_NOT_FOUND, `Asset ${assetId} not found.`);
195
+ a.folderId = folderId;
196
+ this.#audit(em, 'asset.move', a.id, null, { folderId });
197
+ await em.flush();
198
+ return this.detail(a);
199
+ }
200
+ async moveMany(assetIds, folderId) {
201
+ const em = this.deps.emFactory();
202
+ const assets = await em.find(Asset, { id: { $in: assetIds } });
203
+ for (const a of assets)
204
+ a.folderId = folderId;
205
+ if (assets.length > 0) {
206
+ this.#audit(em, 'asset.move_many', folderId ?? 'root', null, {
207
+ folderId,
208
+ assetIds: assets.map((a) => a.id),
209
+ });
210
+ }
211
+ await em.flush();
212
+ return { movedCount: assets.length };
213
+ }
214
+ // — Serialization helpers --------------------------------------------------
215
+ async summary(a) {
216
+ const url = await this.resolveUrl(a.id);
217
+ return {
218
+ id: a.id,
219
+ folderId: a.folderId ?? null,
220
+ filename: a.filename,
221
+ label: a.label ?? null,
222
+ mimeType: a.mimeType,
223
+ sizeBytes: Number(a.sizeBytes),
224
+ visibility: a.visibility,
225
+ storageBackend: a.storageBackend,
226
+ url: url.url,
227
+ createdAt: a.createdAt.toISOString(),
228
+ updatedAt: a.updatedAt.toISOString(),
229
+ deletedAt: a.deletedAt ? a.deletedAt.toISOString() : null,
230
+ pendingCleanup: a.pendingCleanup,
231
+ };
232
+ }
233
+ async detail(a) {
234
+ const summary = await this.summary(a);
235
+ const references = await this.deps.referenceRegistry.findReferences(a.id);
236
+ return {
237
+ ...summary,
238
+ altText: a.altText ?? null,
239
+ references,
240
+ };
241
+ }
242
+ }
243
+ /** Encode a pagination offset as an opaque base64url cursor. */
244
+ function encodeCursor(offset) {
245
+ return Buffer.from(`o:${offset}`, 'utf8').toString('base64url');
246
+ }
247
+ /** Decode an opaque cursor back into a non-negative offset, or null if invalid. */
248
+ function decodeCursor(c) {
249
+ try {
250
+ const raw = Buffer.from(c, 'base64url').toString('utf8');
251
+ const m = raw.match(/^o:(\d+)$/);
252
+ if (!m)
253
+ return null;
254
+ const n = Number(m[1]);
255
+ return Number.isSafeInteger(n) && n >= 0 ? n : null;
256
+ }
257
+ catch {
258
+ return null;
259
+ }
260
+ }
261
+ //# sourceMappingURL=assets-library.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assets-library.service.js","sourceRoot":"","sources":["../../../src/backend/services/assets-library.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import type { AssetEmbedResolution } from '@endora-commerce/contracts';
3
+ import type { AssetsLibraryService } from './assets-library.service.js';
4
+ export declare function findAssetRefIds(body: unknown, acc?: Set<string>): Set<string>;
5
+ export declare function resolveAssetRefs(body: unknown, emFactory: () => EntityManager, service: AssetsLibraryService): Promise<Record<string, AssetEmbedResolution>>;
6
+ //# sourceMappingURL=cms-body-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-body-resolver.d.ts","sourceRoot":"","sources":["../../../src/backend/services/cms-body-resolver.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAEvE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,wBAAgB,eAAe,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAcxF;AAED,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,aAAa,EAC9B,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAC,CAkB/C"}
@@ -0,0 +1,44 @@
1
+ // CMS body asset-ref resolver — feature 013 / US6 / T095.
2
+ //
3
+ // Walks any JSON value, finds nodes with the shape
4
+ // { type: 'asset_ref', assetId: <uuid>, rendering?: ... }
5
+ // and returns a denormalized map keyed by assetId so the storefront
6
+ // CMS-page response can inline ready-to-render URLs alongside the body.
7
+ import { Asset } from '../entities/asset.entity.js';
8
+ export function findAssetRefIds(body, acc = new Set()) {
9
+ if (body === null || body === undefined)
10
+ return acc;
11
+ if (Array.isArray(body)) {
12
+ for (const item of body)
13
+ findAssetRefIds(item, acc);
14
+ return acc;
15
+ }
16
+ if (typeof body === 'object') {
17
+ const obj = body;
18
+ if (obj['type'] === 'asset_ref' && typeof obj['assetId'] === 'string') {
19
+ acc.add(obj['assetId']);
20
+ }
21
+ for (const v of Object.values(obj))
22
+ findAssetRefIds(v, acc);
23
+ }
24
+ return acc;
25
+ }
26
+ export async function resolveAssetRefs(body, emFactory, service) {
27
+ const ids = Array.from(findAssetRefIds(body));
28
+ if (ids.length === 0)
29
+ return {};
30
+ const em = emFactory();
31
+ const assets = await em.find(Asset, { id: { $in: ids }, deletedAt: null });
32
+ const resolutions = await Promise.all(assets.map(async (a) => {
33
+ const url = await service.resolveUrl(a.id);
34
+ return [a.id, {
35
+ url: url.url,
36
+ mimeType: a.mimeType,
37
+ filename: a.filename,
38
+ label: a.label ?? null,
39
+ visibility: a.visibility,
40
+ }];
41
+ }));
42
+ return Object.fromEntries(resolutions);
43
+ }
44
+ //# sourceMappingURL=cms-body-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cms-body-resolver.js","sourceRoot":"","sources":["../../../src/backend/services/cms-body-resolver.ts"],"names":[],"mappings":"AAAA,0DAA0D;AAC1D,EAAE;AACF,mDAAmD;AACnD,4DAA4D;AAC5D,oEAAoE;AACpE,wEAAwE;AAIxE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AAGpD,MAAM,UAAU,eAAe,CAAC,IAAa,EAAE,MAAmB,IAAI,GAAG,EAAE;IACzE,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IACpD,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,KAAK,MAAM,IAAI,IAAI,IAAI;YAAE,eAAe,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;QACpD,OAAO,GAAG,CAAC;IACb,CAAC;IACD,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC7B,MAAM,GAAG,GAAG,IAA+B,CAAC;QAC5C,IAAI,GAAG,CAAC,MAAM,CAAC,KAAK,WAAW,IAAI,OAAO,GAAG,CAAC,SAAS,CAAC,KAAK,QAAQ,EAAE,CAAC;YACtE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1B,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;YAAE,eAAe,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,IAAa,EACb,SAA8B,EAC9B,OAA6B;IAE7B,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,EAAE,GAAG,SAAS,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,GAAG,CACnC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QACrB,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3C,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE;gBACZ,GAAG,EAAE,GAAG,CAAC,GAAG;gBACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,QAAQ,EAAE,CAAC,CAAC,QAAQ;gBACpB,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,IAAI;gBACtB,UAAU,EAAE,CAAC,CAAC,UAAU;aACzB,CAAU,CAAC;IACd,CAAC,CAAC,CACH,CAAC;IACF,OAAO,MAAM,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC;AACzC,CAAC"}
@@ -0,0 +1,29 @@
1
+ import type { EntityManager } from '@mikro-orm/postgresql';
2
+ import { type AssetFolder as AssetFolderDto } from '@endora-commerce/contracts';
3
+ import type { AuditPort } from '@endora-commerce/platform/kernel';
4
+ import type { AssetReferenceRegistry } from './reference-registry.js';
5
+ export declare class FoldersService {
6
+ #private;
7
+ private readonly emFactory;
8
+ private readonly referenceRegistry;
9
+ private readonly auditLog?;
10
+ constructor(emFactory: () => EntityManager, referenceRegistry: AssetReferenceRegistry, auditLog?: AuditPort | undefined);
11
+ listFolderTree(): Promise<AssetFolderDto[]>;
12
+ createFolder(input: {
13
+ parentId: string | null;
14
+ name: string;
15
+ }): Promise<AssetFolderDto>;
16
+ patchFolder(id: string, patch: {
17
+ name?: string;
18
+ parentId?: string | null;
19
+ position?: number;
20
+ }): Promise<AssetFolderDto>;
21
+ deleteFolder(id: string, strategy: 'cancel' | 'moveContentsToParent' | 'deleteRecursively'): Promise<{
22
+ deletedFolderId: string;
23
+ softDeletedAssetIds?: string[];
24
+ }>;
25
+ private collectSubtreeAssetIds;
26
+ private collectSubtreeFolders;
27
+ private toDto;
28
+ }
29
+ //# sourceMappingURL=folders.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders.service.d.ts","sourceRoot":"","sources":["../../../src/backend/services/folders.service.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAe,KAAK,WAAW,IAAI,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAM7F,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,kCAAkC,CAAC;AAClE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEtE,qBAAa,cAAc;;IAEvB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBAFT,SAAS,EAAE,MAAM,aAAa,EAC9B,iBAAiB,EAAE,sBAAsB,EACzC,QAAQ,CAAC,EAAE,SAAS,YAAA;IAqBjC,cAAc,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAqB3C,YAAY,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,CAAC;IAqCvF,WAAW,CACf,EAAE,EAAE,MAAM,EACV,KAAK,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GACpE,OAAO,CAAC,cAAc,CAAC;IAqDpB,YAAY,CAChB,EAAE,EAAE,MAAM,EACV,QAAQ,EAAE,QAAQ,GAAG,sBAAsB,GAAG,mBAAmB,GAChE,OAAO,CAAC;QAAE,eAAe,EAAE,MAAM,CAAC;QAAC,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC;YAwEzD,sBAAsB;YAsBtB,qBAAqB;IAkBnC,OAAO,CAAC,KAAK;CAWd"}
@@ -0,0 +1,231 @@
1
+ // FoldersService — feature 013 / US2. Create, rename, move (with cycle
2
+ // detection), delete (with `ifNonEmpty` strategies). Folders are pure
3
+ // metadata; moving an asset between folders is a metadata-only update,
4
+ // never a physical file move.
5
+ import { ERROR_CODES } from '@endora-commerce/contracts';
6
+ import { HttpError } from '@endora-commerce/platform/http';
7
+ import { AssetFolder } from '../entities/asset-folder.entity.js';
8
+ import { Asset } from '../entities/asset.entity.js';
9
+ import { recordAuditFromContext } from '@endora-commerce/platform/commands';
10
+ export class FoldersService {
11
+ emFactory;
12
+ referenceRegistry;
13
+ auditLog;
14
+ constructor(emFactory, referenceRegistry, auditLog) {
15
+ this.emFactory = emFactory;
16
+ this.referenceRegistry = referenceRegistry;
17
+ this.auditLog = auditLog;
18
+ }
19
+ #audit(em, action, objectId, stateBefore, stateAfter) {
20
+ if (this.auditLog) {
21
+ recordAuditFromContext(this.auditLog, em, {
22
+ action,
23
+ objectType: 'asset_folder',
24
+ objectId,
25
+ stateBefore,
26
+ stateAfter,
27
+ });
28
+ }
29
+ }
30
+ async listFolderTree() {
31
+ const em = this.emFactory();
32
+ const all = await em.find(AssetFolder, {}, { orderBy: { position: 'asc', id: 'asc' } });
33
+ const childrenByParent = new Map();
34
+ for (const f of all) {
35
+ const key = f.parentId ?? null;
36
+ const list = childrenByParent.get(key) ?? [];
37
+ list.push(f.id);
38
+ childrenByParent.set(key, list);
39
+ }
40
+ return all.map((f) => ({
41
+ id: f.id,
42
+ parentId: f.parentId ?? null,
43
+ name: f.name,
44
+ position: f.position,
45
+ childIds: childrenByParent.get(f.id) ?? [],
46
+ createdAt: f.createdAt.toISOString(),
47
+ updatedAt: f.updatedAt.toISOString(),
48
+ }));
49
+ }
50
+ async createFolder(input) {
51
+ const em = this.emFactory();
52
+ if (input.parentId) {
53
+ const parent = await em.findOne(AssetFolder, { id: input.parentId });
54
+ if (!parent) {
55
+ throw new HttpError(404, ERROR_CODES.ASSET_FOLDER_NOT_FOUND, `Parent folder ${input.parentId} not found.`);
56
+ }
57
+ }
58
+ // Compute next position among siblings.
59
+ const siblings = await em.find(AssetFolder, { parentId: input.parentId ?? null });
60
+ const position = siblings.reduce((m, s) => Math.max(m, s.position + 1), 0);
61
+ try {
62
+ const f = em.create(AssetFolder, {
63
+ parentId: input.parentId,
64
+ name: input.name,
65
+ position,
66
+ });
67
+ em.persist(f);
68
+ this.#audit(em, 'asset_folder.create', f.id, null, { name: f.name, parentId: f.parentId });
69
+ await em.flush();
70
+ return this.toDto(f, []);
71
+ }
72
+ catch (e) {
73
+ if (isUniqueViolation(e)) {
74
+ throw new HttpError(409, ERROR_CODES.ASSET_FOLDER_NAME_CONFLICT, `A folder named "${input.name}" already exists in this location.`);
75
+ }
76
+ throw e;
77
+ }
78
+ }
79
+ async patchFolder(id, patch) {
80
+ const em = this.emFactory();
81
+ const f = await em.findOne(AssetFolder, { id });
82
+ if (!f)
83
+ throw new HttpError(404, ERROR_CODES.ASSET_FOLDER_NOT_FOUND, `Folder ${id} not found.`);
84
+ if (patch.parentId !== undefined && patch.parentId !== f.parentId) {
85
+ // Cycle prevention: walk ancestors of the proposed parent.
86
+ if (patch.parentId !== null) {
87
+ if (patch.parentId === id) {
88
+ throw new HttpError(422, ERROR_CODES.ASSET_FOLDER_CYCLE, 'A folder cannot be its own parent.');
89
+ }
90
+ const seen = new Set([id]);
91
+ let cursor = patch.parentId;
92
+ while (cursor) {
93
+ if (seen.has(cursor)) {
94
+ throw new HttpError(422, ERROR_CODES.ASSET_FOLDER_CYCLE, 'Cannot move a folder into its own subtree.');
95
+ }
96
+ seen.add(cursor);
97
+ const next = await em.findOne(AssetFolder, { id: cursor });
98
+ if (!next)
99
+ break;
100
+ cursor = next.parentId ?? null;
101
+ }
102
+ }
103
+ f.parentId = patch.parentId;
104
+ }
105
+ if (patch.name !== undefined)
106
+ f.name = patch.name;
107
+ if (patch.position !== undefined)
108
+ f.position = patch.position;
109
+ this.#audit(em, 'asset_folder.update', f.id, null, { name: f.name, parentId: f.parentId });
110
+ try {
111
+ await em.flush();
112
+ }
113
+ catch (e) {
114
+ if (isUniqueViolation(e)) {
115
+ throw new HttpError(409, ERROR_CODES.ASSET_FOLDER_NAME_CONFLICT, `A folder with this name already exists at the target location.`);
116
+ }
117
+ throw e;
118
+ }
119
+ const children = await em.find(AssetFolder, { parentId: f.id });
120
+ return this.toDto(f, children.map((c) => c.id));
121
+ }
122
+ async deleteFolder(id, strategy) {
123
+ const em = this.emFactory();
124
+ const f = await em.findOne(AssetFolder, { id });
125
+ if (!f)
126
+ throw new HttpError(404, ERROR_CODES.ASSET_FOLDER_NOT_FOUND, `Folder ${id} not found.`);
127
+ // Audit persists on `em`; only committed by the flush in whichever strategy
128
+ // branch actually deletes (a `cancel`/refs-blocked path throws before flush).
129
+ this.#audit(em, 'asset_folder.delete', f.id, { name: f.name, strategy }, null);
130
+ const childFolders = await em.find(AssetFolder, { parentId: id });
131
+ const directAssets = await em.find(Asset, { folderId: id });
132
+ if (strategy === 'cancel' && (childFolders.length > 0 || directAssets.length > 0)) {
133
+ throw new HttpError(409, ERROR_CODES.ASSET_FOLDER_NOT_EMPTY, `Folder is not empty (${childFolders.length} sub-folder(s), ${directAssets.length} asset(s)).`);
134
+ }
135
+ if (strategy === 'moveContentsToParent') {
136
+ for (const cf of childFolders)
137
+ cf.parentId = f.parentId ?? null;
138
+ for (const a of directAssets)
139
+ a.folderId = f.parentId ?? null;
140
+ await em.flush();
141
+ em.remove(f);
142
+ await em.flush();
143
+ return { deletedFolderId: id };
144
+ }
145
+ if (strategy === 'deleteRecursively') {
146
+ // Walk the subtree, gather every asset id, check refs all-or-nothing.
147
+ const subtreeIds = await this.collectSubtreeAssetIds(em, id);
148
+ if (subtreeIds.length > 0) {
149
+ const refs = await this.referenceRegistry.findReferencesMany(subtreeIds);
150
+ const blocking = [];
151
+ for (const [aid, list] of refs.entries()) {
152
+ if (list.length > 0)
153
+ blocking.push(aid);
154
+ }
155
+ if (blocking.length > 0) {
156
+ throw new HttpError(409, ERROR_CODES.ASSET_REFERENCED, `Cannot delete folder: ${blocking.length} asset(s) in this subtree are still referenced.`, blocking.slice(0, 20).map((aid) => ({ path: 'assetId', issue: aid })));
157
+ }
158
+ }
159
+ // Soft-delete all assets in subtree.
160
+ const now = new Date();
161
+ const retentionDays = 30;
162
+ const purgeAt = new Date(now.getTime() + retentionDays * 24 * 60 * 60 * 1000);
163
+ for (const aid of subtreeIds) {
164
+ const a = await em.findOneOrFail(Asset, { id: aid });
165
+ a.deletedAt = now;
166
+ a.purgeAfterAt = purgeAt;
167
+ }
168
+ // Delete sub-folders bottom-up by setting parent_id NULL on every
169
+ // intermediate, then removing.
170
+ const folders = await this.collectSubtreeFolders(em, id);
171
+ for (const sub of folders) {
172
+ em.remove(sub);
173
+ }
174
+ em.remove(f);
175
+ await em.flush();
176
+ return { deletedFolderId: id, softDeletedAssetIds: subtreeIds };
177
+ }
178
+ // strategy === 'cancel' and folder is empty — straight delete.
179
+ em.remove(f);
180
+ await em.flush();
181
+ return { deletedFolderId: id };
182
+ }
183
+ async collectSubtreeAssetIds(em, rootId) {
184
+ const folderIds = [rootId];
185
+ const queue = [rootId];
186
+ while (queue.length > 0) {
187
+ const head = queue.shift();
188
+ const children = await em.find(AssetFolder, { parentId: head });
189
+ for (const c of children) {
190
+ folderIds.push(c.id);
191
+ queue.push(c.id);
192
+ }
193
+ }
194
+ const assets = await em.find(Asset, { folderId: { $in: folderIds }, deletedAt: null }, { fields: ['id'] });
195
+ return assets.map((a) => a.id);
196
+ }
197
+ async collectSubtreeFolders(em, rootId) {
198
+ const acc = [];
199
+ const queue = [rootId];
200
+ while (queue.length > 0) {
201
+ const head = queue.shift();
202
+ if (head !== rootId) {
203
+ const cur = await em.findOne(AssetFolder, { id: head });
204
+ if (cur)
205
+ acc.push(cur);
206
+ }
207
+ const children = await em.find(AssetFolder, { parentId: head });
208
+ for (const c of children)
209
+ queue.push(c.id);
210
+ }
211
+ return acc;
212
+ }
213
+ toDto(f, childIds) {
214
+ return {
215
+ id: f.id,
216
+ parentId: f.parentId ?? null,
217
+ name: f.name,
218
+ position: f.position,
219
+ childIds,
220
+ createdAt: f.createdAt.toISOString(),
221
+ updatedAt: f.updatedAt.toISOString(),
222
+ };
223
+ }
224
+ }
225
+ function isUniqueViolation(e) {
226
+ return (e !== null &&
227
+ typeof e === 'object' &&
228
+ e.constructor?.name ===
229
+ 'UniqueConstraintViolationException');
230
+ }
231
+ //# sourceMappingURL=folders.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folders.service.js","sourceRoot":"","sources":["../../../src/backend/services/folders.service.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,sEAAsE;AACtE,uEAAuE;AACvE,8BAA8B;AAG9B,OAAO,EAAE,WAAW,EAAsC,MAAM,4BAA4B,CAAC;AAE7F,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,oCAAoC,CAAC;AACjE,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAI5E,MAAM,OAAO,cAAc;IAEN;IACA;IACA;IAHnB,YACmB,SAA8B,EAC9B,iBAAyC,EACzC,QAAoB;QAFpB,cAAS,GAAT,SAAS,CAAqB;QAC9B,sBAAiB,GAAjB,iBAAiB,CAAwB;QACzC,aAAQ,GAAR,QAAQ,CAAY;IACpC,CAAC;IAEJ,MAAM,CACJ,EAAiB,EACjB,MAAc,EACd,QAAgB,EAChB,WAA2C,EAC3C,UAA0C;QAE1C,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,sBAAsB,CAAC,IAAI,CAAC,QAAQ,EAAE,EAAE,EAAE;gBACxC,MAAM;gBACN,UAAU,EAAE,cAAc;gBAC1B,QAAQ;gBACR,WAAW;gBACX,UAAU;aACX,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;QACxF,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA2B,CAAC;QAC5D,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;YACpB,MAAM,GAAG,GAAG,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC;YAC/B,MAAM,IAAI,GAAG,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;YAC7C,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAChB,gBAAgB,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACrB,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;YAC5B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ,EAAE,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE;YAC1C,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;YACpC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;SACrC,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAgD;QACjE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;YACnB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC;YACrE,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,sBAAsB,EAClC,iBAAiB,KAAK,CAAC,QAAQ,aAAa,CAC7C,CAAC;YACJ,CAAC;QACH,CAAC;QACD,wCAAwC;QACxC,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC,CAAC;QAClF,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC3E,IAAI,CAAC;YACH,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE;gBAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;gBACxB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,QAAQ;aACT,CAAC,CAAC;YACH,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC3F,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC3B,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,0BAA0B,EACtC,mBAAmB,KAAK,CAAC,IAAI,oCAAoC,CAClE,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW,CACf,EAAU,EACV,KAAqE;QAErE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,sBAAsB,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QAEhG,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,CAAC,CAAC,QAAQ,EAAE,CAAC;YAClE,2DAA2D;YAC3D,IAAI,KAAK,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;gBAC5B,IAAI,KAAK,CAAC,QAAQ,KAAK,EAAE,EAAE,CAAC;oBAC1B,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,kBAAkB,EAC9B,oCAAoC,CACrC,CAAC;gBACJ,CAAC;gBACD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAS,CAAC,EAAE,CAAC,CAAC,CAAC;gBACnC,IAAI,MAAM,GAAkB,KAAK,CAAC,QAAQ,CAAC;gBAC3C,OAAO,MAAM,EAAE,CAAC;oBACd,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;wBACrB,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,kBAAkB,EAC9B,4CAA4C,CAC7C,CAAC;oBACJ,CAAC;oBACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;oBACjB,MAAM,IAAI,GAAuB,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;oBAC/E,IAAI,CAAC,IAAI;wBAAE,MAAM;oBACjB,MAAM,GAAG,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC;gBACjC,CAAC;YACH,CAAC;YACD,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC9B,CAAC;QACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS;YAAE,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QAClD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS;YAAE,CAAC,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC;QAE9D,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC3F,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACnB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC;gBACzB,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,0BAA0B,EACtC,gEAAgE,CACjE,CAAC;YACJ,CAAC;YACD,MAAM,CAAC,CAAC;QACV,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChE,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAClD,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,EAAU,EACV,QAAiE;QAEjE,MAAM,EAAE,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC;YAAE,MAAM,IAAI,SAAS,CAAC,GAAG,EAAE,WAAW,CAAC,sBAAsB,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;QAChG,4EAA4E;QAC5E,8EAA8E;QAC9E,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,qBAAqB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;QAE/E,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC;QAE5D,IAAI,QAAQ,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;YAClF,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,sBAAsB,EAClC,wBAAwB,YAAY,CAAC,MAAM,mBAAmB,YAAY,CAAC,MAAM,aAAa,CAC/F,CAAC;QACJ,CAAC;QAED,IAAI,QAAQ,KAAK,sBAAsB,EAAE,CAAC;YACxC,KAAK,MAAM,EAAE,IAAI,YAAY;gBAAE,EAAE,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC;YAChE,KAAK,MAAM,CAAC,IAAI,YAAY;gBAAE,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,QAAQ,IAAI,IAAI,CAAC;YAC9D,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;QACjC,CAAC;QAED,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;YACrC,sEAAsE;YACtE,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC7D,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC;gBACzE,MAAM,QAAQ,GAAa,EAAE,CAAC;gBAC9B,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC;oBACzC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;wBAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;gBAC1C,CAAC;gBACD,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,MAAM,IAAI,SAAS,CACjB,GAAG,EACH,WAAW,CAAC,gBAAgB,EAC5B,yBAAyB,QAAQ,CAAC,MAAM,iDAAiD,EACzF,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC,CACtE,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,qCAAqC;YACrC,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,aAAa,GAAG,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,aAAa,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;YAC9E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,MAAM,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,CAAC,CAAC;gBACrD,CAAC,CAAC,SAAS,GAAG,GAAG,CAAC;gBAClB,CAAC,CAAC,YAAY,GAAG,OAAO,CAAC;YAC3B,CAAC;YACD,kEAAkE;YAClE,+BAA+B;YAC/B,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,qBAAqB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YACzD,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YACjB,CAAC;YACD,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YACb,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;YACjB,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC;QAClE,CAAC;QAED,+DAA+D;QAC/D,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACb,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;QACjB,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,sBAAsB,CAClC,EAAiB,EACjB,MAAc;QAEd,MAAM,SAAS,GAAa,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YAC5B,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;gBACzB,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBACrB,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAC1B,KAAK,EACL,EAAE,QAAQ,EAAE,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,EACjD,EAAE,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CACnB,CAAC;QACF,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjC,CAAC;IAEO,KAAK,CAAC,qBAAqB,CACjC,EAAiB,EACjB,MAAc;QAEd,MAAM,GAAG,GAAkB,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAa,CAAC,MAAM,CAAC,CAAC;QACjC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACxB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAG,CAAC;YAC5B,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;gBACpB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;gBACxD,IAAI,GAAG;oBAAE,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YACD,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YAChE,KAAK,MAAM,CAAC,IAAI,QAAQ;gBAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAEO,KAAK,CAAC,CAAc,EAAE,QAAkB;QAC9C,OAAO;YACL,EAAE,EAAE,CAAC,CAAC,EAAE;YACR,QAAQ,EAAE,CAAC,CAAC,QAAQ,IAAI,IAAI;YAC5B,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,QAAQ;YACR,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;YACpC,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,WAAW,EAAE;SACrC,CAAC;IACJ,CAAC;CACF;AAED,SAAS,iBAAiB,CAAC,CAAU;IACnC,OAAO,CACL,CAAC,KAAK,IAAI;QACV,OAAO,CAAC,KAAK,QAAQ;QACpB,CAAyC,CAAC,WAAW,EAAE,IAAI;YAC1D,oCAAoC,CACvC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ export interface SignedTokenInput {
2
+ /** Asset id this token authorizes. */
3
+ assetId: string;
4
+ /** Unix-seconds expiry. */
5
+ exp: number;
6
+ }
7
+ export interface VerificationContext {
8
+ assetId: string;
9
+ /** The full token string from the URL. */
10
+ token: string;
11
+ /** The full exp value from the URL (seconds). */
12
+ exp: number;
13
+ /** Now (seconds since epoch). Injectable for tests. */
14
+ nowSec: number;
15
+ }
16
+ export declare class HmacSigner {
17
+ private readonly key;
18
+ constructor(key: Buffer);
19
+ static fromEnv(envKey?: string | undefined): HmacSigner;
20
+ sign(input: SignedTokenInput): string;
21
+ /**
22
+ * Returns true when `ctx.token` is a valid signature for
23
+ * (`ctx.assetId`, `ctx.exp`) and `ctx.exp >= ctx.nowSec`. Returns false on
24
+ * any failure (mismatch, expiry, malformed). Uses `timingSafeEqual`.
25
+ */
26
+ verify(ctx: VerificationContext): boolean;
27
+ }
28
+ //# sourceMappingURL=hmac.d.ts.map