@momentumcms/core 0.5.1 → 0.5.2
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/package.json
CHANGED
package/src/index.cjs
CHANGED
|
@@ -445,6 +445,31 @@ function validateRowCount(name, label, count, minRows, maxRows, errors) {
|
|
|
445
445
|
}
|
|
446
446
|
|
|
447
447
|
// libs/core/src/lib/collections/media.collection.ts
|
|
448
|
+
var validateFocalPoint = (value) => {
|
|
449
|
+
if (value === null || value === void 0)
|
|
450
|
+
return true;
|
|
451
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
452
|
+
return "Focal point must be an object with x and y coordinates";
|
|
453
|
+
}
|
|
454
|
+
const fp = Object.fromEntries(Object.entries(value));
|
|
455
|
+
if (!("x" in fp) || !("y" in fp)) {
|
|
456
|
+
return "Focal point must have both x and y properties";
|
|
457
|
+
}
|
|
458
|
+
const { x, y } = fp;
|
|
459
|
+
if (typeof x !== "number" || !Number.isFinite(x)) {
|
|
460
|
+
return "Focal point x must be a finite number";
|
|
461
|
+
}
|
|
462
|
+
if (typeof y !== "number" || !Number.isFinite(y)) {
|
|
463
|
+
return "Focal point y must be a finite number";
|
|
464
|
+
}
|
|
465
|
+
if (x < 0 || x > 1) {
|
|
466
|
+
return `Focal point x must be between 0 and 1 (received ${x})`;
|
|
467
|
+
}
|
|
468
|
+
if (y < 0 || y > 1) {
|
|
469
|
+
return `Focal point y must be between 0 and 1 (received ${y})`;
|
|
470
|
+
}
|
|
471
|
+
return true;
|
|
472
|
+
};
|
|
448
473
|
var MediaCollection = defineCollection({
|
|
449
474
|
slug: "media",
|
|
450
475
|
labels: {
|
|
@@ -499,6 +524,14 @@ var MediaCollection = defineCollection({
|
|
|
499
524
|
json("focalPoint", {
|
|
500
525
|
label: "Focal Point",
|
|
501
526
|
description: "Focal point coordinates for image cropping",
|
|
527
|
+
validate: validateFocalPoint,
|
|
528
|
+
admin: {
|
|
529
|
+
hidden: true
|
|
530
|
+
}
|
|
531
|
+
}),
|
|
532
|
+
json("sizes", {
|
|
533
|
+
label: "Image Sizes",
|
|
534
|
+
description: "Generated image size variants",
|
|
502
535
|
admin: {
|
|
503
536
|
hidden: true
|
|
504
537
|
}
|
package/src/index.js
CHANGED
|
@@ -364,6 +364,31 @@ function validateRowCount(name, label, count, minRows, maxRows, errors) {
|
|
|
364
364
|
}
|
|
365
365
|
|
|
366
366
|
// libs/core/src/lib/collections/media.collection.ts
|
|
367
|
+
var validateFocalPoint = (value) => {
|
|
368
|
+
if (value === null || value === void 0)
|
|
369
|
+
return true;
|
|
370
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
371
|
+
return "Focal point must be an object with x and y coordinates";
|
|
372
|
+
}
|
|
373
|
+
const fp = Object.fromEntries(Object.entries(value));
|
|
374
|
+
if (!("x" in fp) || !("y" in fp)) {
|
|
375
|
+
return "Focal point must have both x and y properties";
|
|
376
|
+
}
|
|
377
|
+
const { x, y } = fp;
|
|
378
|
+
if (typeof x !== "number" || !Number.isFinite(x)) {
|
|
379
|
+
return "Focal point x must be a finite number";
|
|
380
|
+
}
|
|
381
|
+
if (typeof y !== "number" || !Number.isFinite(y)) {
|
|
382
|
+
return "Focal point y must be a finite number";
|
|
383
|
+
}
|
|
384
|
+
if (x < 0 || x > 1) {
|
|
385
|
+
return `Focal point x must be between 0 and 1 (received ${x})`;
|
|
386
|
+
}
|
|
387
|
+
if (y < 0 || y > 1) {
|
|
388
|
+
return `Focal point y must be between 0 and 1 (received ${y})`;
|
|
389
|
+
}
|
|
390
|
+
return true;
|
|
391
|
+
};
|
|
367
392
|
var MediaCollection = defineCollection({
|
|
368
393
|
slug: "media",
|
|
369
394
|
labels: {
|
|
@@ -418,6 +443,14 @@ var MediaCollection = defineCollection({
|
|
|
418
443
|
json("focalPoint", {
|
|
419
444
|
label: "Focal Point",
|
|
420
445
|
description: "Focal point coordinates for image cropping",
|
|
446
|
+
validate: validateFocalPoint,
|
|
447
|
+
admin: {
|
|
448
|
+
hidden: true
|
|
449
|
+
}
|
|
450
|
+
}),
|
|
451
|
+
json("sizes", {
|
|
452
|
+
label: "Image Sizes",
|
|
453
|
+
description: "Generated image size variants",
|
|
421
454
|
admin: {
|
|
422
455
|
hidden: true
|
|
423
456
|
}
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Defines the structure of collections (similar to Payload CMS)
|
|
4
4
|
*/
|
|
5
5
|
import type { Field } from '../fields/field.types';
|
|
6
|
+
import type { ImageSizeConfig } from '../storage';
|
|
6
7
|
export interface AccessArgs {
|
|
7
8
|
req: RequestContext;
|
|
8
9
|
id?: string | number;
|
|
@@ -137,6 +138,10 @@ export interface UploadCollectionConfig {
|
|
|
137
138
|
pathField?: string;
|
|
138
139
|
/** Field name for the public URL. @default 'url' */
|
|
139
140
|
urlField?: string;
|
|
141
|
+
/** Image sizes to generate on upload (images only) */
|
|
142
|
+
imageSizes?: ImageSizeConfig[];
|
|
143
|
+
/** Default output format for generated sizes. @default 'original' */
|
|
144
|
+
formatPreference?: 'jpeg' | 'webp' | 'avif' | 'original';
|
|
140
145
|
}
|
|
141
146
|
export interface TimestampsConfig {
|
|
142
147
|
/** Add createdAt field */
|
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
* Built-in Media Collection for Momentum CMS
|
|
3
3
|
* Stores metadata for uploaded files
|
|
4
4
|
*/
|
|
5
|
+
import type { ValidateFunction } from '../fields/field.types';
|
|
6
|
+
/**
|
|
7
|
+
* Validates a focalPoint value: null/undefined is allowed (optional field).
|
|
8
|
+
* When present, must be a plain object with exactly `x` and `y` properties,
|
|
9
|
+
* both finite numbers in the [0, 1] range.
|
|
10
|
+
*/
|
|
11
|
+
export declare const validateFocalPoint: ValidateFunction;
|
|
5
12
|
/**
|
|
6
13
|
* Built-in Media collection for storing file upload metadata.
|
|
7
14
|
* Users can override this by defining their own 'media' collection.
|
|
@@ -24,6 +31,14 @@ export interface MediaDocument {
|
|
|
24
31
|
x: number;
|
|
25
32
|
y: number;
|
|
26
33
|
};
|
|
34
|
+
sizes?: Record<string, {
|
|
35
|
+
url: string;
|
|
36
|
+
path: string;
|
|
37
|
+
width: number;
|
|
38
|
+
height: number;
|
|
39
|
+
mimeType: string;
|
|
40
|
+
filesize: number;
|
|
41
|
+
}>;
|
|
27
42
|
createdAt: string;
|
|
28
43
|
updatedAt: string;
|
|
29
44
|
}
|
|
@@ -1,7 +1,57 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Storage module for Momentum CMS
|
|
3
|
-
* Defines interfaces for file storage adapters
|
|
3
|
+
* Defines interfaces for file storage adapters and image processing
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Describes one output size for image processing.
|
|
7
|
+
*/
|
|
8
|
+
export interface ImageSizeConfig {
|
|
9
|
+
/** Named key for this size (e.g. 'thumbnail', 'medium') */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Target width in pixels. Undefined = proportional from height. */
|
|
12
|
+
width?: number;
|
|
13
|
+
/** Target height in pixels. Undefined = proportional from width. */
|
|
14
|
+
height?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Resizing strategy.
|
|
17
|
+
* - 'contain': shrink to fit, no cropping
|
|
18
|
+
* - 'cover': resize + crop to fill exact dimensions (uses focalPoint)
|
|
19
|
+
* - 'fill': stretch to exact dimensions
|
|
20
|
+
* - 'width': resize to width, height proportional
|
|
21
|
+
* - 'height': resize to height, width proportional
|
|
22
|
+
* @default 'cover'
|
|
23
|
+
*/
|
|
24
|
+
fit?: 'contain' | 'cover' | 'fill' | 'width' | 'height';
|
|
25
|
+
/** Output format. When undefined, uses source format or global formatPreference. */
|
|
26
|
+
format?: 'jpeg' | 'webp' | 'avif' | 'png';
|
|
27
|
+
/** JPEG/WebP/AVIF quality (1-100). @default 80 */
|
|
28
|
+
quality?: number;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Image dimensions in pixels.
|
|
32
|
+
*/
|
|
33
|
+
export interface ImageDimensions {
|
|
34
|
+
width: number;
|
|
35
|
+
height: number;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Pluggable image processor interface.
|
|
39
|
+
* Implement this to provide custom image processing backends.
|
|
40
|
+
*/
|
|
41
|
+
export interface ImageProcessor {
|
|
42
|
+
/** Detect image dimensions without full decode when possible. */
|
|
43
|
+
getDimensions(buffer: Uint8Array, mimeType: string): Promise<ImageDimensions>;
|
|
44
|
+
/** Process one size variant. Returns the processed buffer and its dimensions. */
|
|
45
|
+
processVariant(buffer: Uint8Array, mimeType: string, size: ImageSizeConfig, focalPoint?: {
|
|
46
|
+
x: number;
|
|
47
|
+
y: number;
|
|
48
|
+
}): Promise<{
|
|
49
|
+
buffer: Uint8Array;
|
|
50
|
+
width: number;
|
|
51
|
+
height: number;
|
|
52
|
+
mimeType: string;
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
5
55
|
/**
|
|
6
56
|
* Represents an uploaded file before storage.
|
|
7
57
|
*/
|