@uptrademedia/site-kit 1.0.9 → 1.0.10
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/dist/api-CWtoFJCO.d.mts +137 -0
- package/dist/api-CWtoFJCO.d.ts +137 -0
- package/dist/{api-QUIPJJCX.js → api-UBHLAPUG.js} +20 -20
- package/dist/api-UBHLAPUG.js.map +1 -0
- package/dist/{api-V3BA5PMX.mjs → api-XNF6Q5HO.mjs} +3 -3
- package/dist/api-XNF6Q5HO.mjs.map +1 -0
- package/dist/{chunk-QQB4FO4Q.js → chunk-AWAJEIZS.js} +11 -8
- package/dist/chunk-AWAJEIZS.js.map +1 -0
- package/dist/{chunk-MB3WR5KJ.mjs → chunk-CDJL2YGL.mjs} +61 -443
- package/dist/chunk-CDJL2YGL.mjs.map +1 -0
- package/dist/{chunk-TDK7DLCH.js → chunk-FLAA4ZJO.js} +59 -448
- package/dist/chunk-FLAA4ZJO.js.map +1 -0
- package/dist/{chunk-JGQPAXTL.mjs → chunk-H5AGHERY.mjs} +8 -5
- package/dist/chunk-H5AGHERY.mjs.map +1 -0
- package/dist/{chunk-VDI7KYME.js → chunk-IYVJGUYX.js} +8 -4
- package/dist/chunk-IYVJGUYX.js.map +1 -0
- package/dist/{chunk-FQVGK746.mjs → chunk-SKHOW2CI.mjs} +8 -4
- package/dist/chunk-SKHOW2CI.mjs.map +1 -0
- package/dist/cli/index.js +32 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +32 -25
- package/dist/cli/index.mjs.map +1 -1
- package/dist/images/index.d.mts +49 -126
- package/dist/images/index.d.ts +49 -126
- package/dist/images/index.js +12 -12
- package/dist/images/index.mjs +1 -5
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +510 -106
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +440 -13
- package/dist/index.mjs.map +1 -1
- package/dist/{routing-CIOFpFCB.d.mts → routing-BT0RrBLk.d.mts} +14 -1
- package/dist/{routing-CF91y6NO.d.ts → routing-wmNSxSvP.d.ts} +14 -1
- package/dist/seo/index.d.mts +37 -4
- package/dist/seo/index.d.ts +37 -4
- package/dist/seo/index.js +48 -18
- package/dist/seo/index.js.map +1 -1
- package/dist/seo/index.mjs +34 -5
- package/dist/seo/index.mjs.map +1 -1
- package/dist/seo/server.d.mts +15 -4
- package/dist/seo/server.d.ts +15 -4
- package/dist/seo/server.js +16 -16
- package/dist/seo/server.mjs +2 -2
- package/dist/{types-j8X4vUhB.d.mts → types-wf4dwNMO.d.mts} +5 -0
- package/dist/{types-j8X4vUhB.d.ts → types-wf4dwNMO.d.ts} +5 -0
- package/package.json +1 -1
- package/dist/api-QUIPJJCX.js.map +0 -1
- package/dist/api-V3BA5PMX.mjs.map +0 -1
- package/dist/chunk-FQVGK746.mjs.map +0 -1
- package/dist/chunk-JGQPAXTL.mjs.map +0 -1
- package/dist/chunk-MB3WR5KJ.mjs.map +0 -1
- package/dist/chunk-QQB4FO4Q.js.map +0 -1
- package/dist/chunk-TDK7DLCH.js.map +0 -1
- package/dist/chunk-VDI7KYME.js.map +0 -1
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
|
|
4
|
+
interface ManagedImageData {
|
|
5
|
+
id: string;
|
|
6
|
+
slot_id: string;
|
|
7
|
+
page_path: string | null;
|
|
8
|
+
file_id: string | null;
|
|
9
|
+
external_url: string | null;
|
|
10
|
+
alt_text: string | null;
|
|
11
|
+
title: string | null;
|
|
12
|
+
caption: string | null;
|
|
13
|
+
focal_point_x: number;
|
|
14
|
+
focal_point_y: number;
|
|
15
|
+
aspect_ratio: string | null;
|
|
16
|
+
public_url?: string;
|
|
17
|
+
is_placeholder: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface ImageFile {
|
|
20
|
+
id: string;
|
|
21
|
+
filename: string;
|
|
22
|
+
storage_path: string;
|
|
23
|
+
mime_type: string;
|
|
24
|
+
file_size: number;
|
|
25
|
+
folder_path: string | null;
|
|
26
|
+
public_url?: string;
|
|
27
|
+
}
|
|
28
|
+
interface ManagedImageProps {
|
|
29
|
+
/** API key for Portal API */
|
|
30
|
+
apiKey?: string;
|
|
31
|
+
/** API URL (defaults to https://api.uptrademedia.com) */
|
|
32
|
+
apiUrl?: string;
|
|
33
|
+
/** Unique slot identifier (e.g., 'hero-background', 'about-team-1') */
|
|
34
|
+
slotId: string;
|
|
35
|
+
/** Page path for page-specific slots (defaults to current path) */
|
|
36
|
+
pagePath?: string;
|
|
37
|
+
/** Fallback alt text if not set in Portal */
|
|
38
|
+
alt?: string;
|
|
39
|
+
/** CSS class names */
|
|
40
|
+
className?: string;
|
|
41
|
+
/** Image width */
|
|
42
|
+
width?: number | string;
|
|
43
|
+
/** Image height */
|
|
44
|
+
height?: number | string;
|
|
45
|
+
/** CSS object-fit property */
|
|
46
|
+
objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
47
|
+
/** Fallback image URL when no image assigned */
|
|
48
|
+
fallback?: string;
|
|
49
|
+
/** Custom placeholder component */
|
|
50
|
+
placeholder?: React__default.ReactNode;
|
|
51
|
+
/** Called when image loads */
|
|
52
|
+
onLoad?: () => void;
|
|
53
|
+
/** Called on error */
|
|
54
|
+
onError?: (error: Error) => void;
|
|
55
|
+
/** Priority loading (Next.js Image optimization) */
|
|
56
|
+
priority?: boolean;
|
|
57
|
+
/** Additional styles */
|
|
58
|
+
style?: React__default.CSSProperties;
|
|
59
|
+
/** Enable dev picker even outside dev mode */
|
|
60
|
+
forceDevMode?: boolean;
|
|
61
|
+
}
|
|
62
|
+
declare function ManagedImage({ apiKey, apiUrl, slotId, pagePath, alt, className, width, height, objectFit, fallback, placeholder, onLoad, onError, priority, style, forceDevMode, }: ManagedImageProps): react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Images API functions
|
|
66
|
+
*
|
|
67
|
+
* All functions use Portal API with API key authentication.
|
|
68
|
+
* Never makes direct Supabase calls.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
interface ImageApiConfig {
|
|
72
|
+
apiUrl: string;
|
|
73
|
+
apiKey: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fetch a managed image for a specific slot
|
|
77
|
+
*/
|
|
78
|
+
declare function fetchManagedImage(config: ImageApiConfig, slotId: string, pagePath?: string): Promise<{
|
|
79
|
+
image: ManagedImageData | null;
|
|
80
|
+
is_placeholder: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Fetch all managed images for the project
|
|
84
|
+
*/
|
|
85
|
+
declare function fetchManagedImages(config: ImageApiConfig, options?: {
|
|
86
|
+
pagePath?: string;
|
|
87
|
+
category?: string;
|
|
88
|
+
includePlaceholders?: boolean;
|
|
89
|
+
}): Promise<{
|
|
90
|
+
images: ManagedImageData[];
|
|
91
|
+
}>;
|
|
92
|
+
/**
|
|
93
|
+
* List available image files in the project
|
|
94
|
+
*/
|
|
95
|
+
declare function listImageFiles(config: ImageApiConfig, options?: {
|
|
96
|
+
folder?: string;
|
|
97
|
+
search?: string;
|
|
98
|
+
}): Promise<{
|
|
99
|
+
files: ImageFile[];
|
|
100
|
+
folders: string[];
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Upload a new image
|
|
104
|
+
*/
|
|
105
|
+
declare function uploadImage(config: ImageApiConfig, file: File, options?: {
|
|
106
|
+
slotId?: string;
|
|
107
|
+
pagePath?: string;
|
|
108
|
+
folder?: string;
|
|
109
|
+
altText?: string;
|
|
110
|
+
}): Promise<{
|
|
111
|
+
file: ImageFile;
|
|
112
|
+
image?: ManagedImageData;
|
|
113
|
+
}>;
|
|
114
|
+
/**
|
|
115
|
+
* Assign an existing file to an image slot
|
|
116
|
+
*/
|
|
117
|
+
declare function assignImageToSlot(config: ImageApiConfig, slotId: string, options: {
|
|
118
|
+
fileId?: string;
|
|
119
|
+
externalUrl?: string;
|
|
120
|
+
pagePath?: string;
|
|
121
|
+
altText?: string;
|
|
122
|
+
title?: string;
|
|
123
|
+
caption?: string;
|
|
124
|
+
focalPointX?: number;
|
|
125
|
+
focalPointY?: number;
|
|
126
|
+
aspectRatio?: string;
|
|
127
|
+
}): Promise<{
|
|
128
|
+
image: ManagedImageData;
|
|
129
|
+
}>;
|
|
130
|
+
/**
|
|
131
|
+
* Clear an image from a slot (keeps the file)
|
|
132
|
+
*/
|
|
133
|
+
declare function clearImageSlot(config: ImageApiConfig, slotId: string, pagePath?: string): Promise<{
|
|
134
|
+
success: boolean;
|
|
135
|
+
}>;
|
|
136
|
+
|
|
137
|
+
export { type ImageFile as I, ManagedImage as M, type ManagedImageProps as a, type ManagedImageData as b, fetchManagedImages as c, assignImageToSlot as d, clearImageSlot as e, fetchManagedImage as f, type ImageApiConfig as g, listImageFiles as l, uploadImage as u };
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import React__default from 'react';
|
|
3
|
+
|
|
4
|
+
interface ManagedImageData {
|
|
5
|
+
id: string;
|
|
6
|
+
slot_id: string;
|
|
7
|
+
page_path: string | null;
|
|
8
|
+
file_id: string | null;
|
|
9
|
+
external_url: string | null;
|
|
10
|
+
alt_text: string | null;
|
|
11
|
+
title: string | null;
|
|
12
|
+
caption: string | null;
|
|
13
|
+
focal_point_x: number;
|
|
14
|
+
focal_point_y: number;
|
|
15
|
+
aspect_ratio: string | null;
|
|
16
|
+
public_url?: string;
|
|
17
|
+
is_placeholder: boolean;
|
|
18
|
+
}
|
|
19
|
+
interface ImageFile {
|
|
20
|
+
id: string;
|
|
21
|
+
filename: string;
|
|
22
|
+
storage_path: string;
|
|
23
|
+
mime_type: string;
|
|
24
|
+
file_size: number;
|
|
25
|
+
folder_path: string | null;
|
|
26
|
+
public_url?: string;
|
|
27
|
+
}
|
|
28
|
+
interface ManagedImageProps {
|
|
29
|
+
/** API key for Portal API */
|
|
30
|
+
apiKey?: string;
|
|
31
|
+
/** API URL (defaults to https://api.uptrademedia.com) */
|
|
32
|
+
apiUrl?: string;
|
|
33
|
+
/** Unique slot identifier (e.g., 'hero-background', 'about-team-1') */
|
|
34
|
+
slotId: string;
|
|
35
|
+
/** Page path for page-specific slots (defaults to current path) */
|
|
36
|
+
pagePath?: string;
|
|
37
|
+
/** Fallback alt text if not set in Portal */
|
|
38
|
+
alt?: string;
|
|
39
|
+
/** CSS class names */
|
|
40
|
+
className?: string;
|
|
41
|
+
/** Image width */
|
|
42
|
+
width?: number | string;
|
|
43
|
+
/** Image height */
|
|
44
|
+
height?: number | string;
|
|
45
|
+
/** CSS object-fit property */
|
|
46
|
+
objectFit?: 'cover' | 'contain' | 'fill' | 'none' | 'scale-down';
|
|
47
|
+
/** Fallback image URL when no image assigned */
|
|
48
|
+
fallback?: string;
|
|
49
|
+
/** Custom placeholder component */
|
|
50
|
+
placeholder?: React__default.ReactNode;
|
|
51
|
+
/** Called when image loads */
|
|
52
|
+
onLoad?: () => void;
|
|
53
|
+
/** Called on error */
|
|
54
|
+
onError?: (error: Error) => void;
|
|
55
|
+
/** Priority loading (Next.js Image optimization) */
|
|
56
|
+
priority?: boolean;
|
|
57
|
+
/** Additional styles */
|
|
58
|
+
style?: React__default.CSSProperties;
|
|
59
|
+
/** Enable dev picker even outside dev mode */
|
|
60
|
+
forceDevMode?: boolean;
|
|
61
|
+
}
|
|
62
|
+
declare function ManagedImage({ apiKey, apiUrl, slotId, pagePath, alt, className, width, height, objectFit, fallback, placeholder, onLoad, onError, priority, style, forceDevMode, }: ManagedImageProps): react_jsx_runtime.JSX.Element;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Images API functions
|
|
66
|
+
*
|
|
67
|
+
* All functions use Portal API with API key authentication.
|
|
68
|
+
* Never makes direct Supabase calls.
|
|
69
|
+
*/
|
|
70
|
+
|
|
71
|
+
interface ImageApiConfig {
|
|
72
|
+
apiUrl: string;
|
|
73
|
+
apiKey: string;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Fetch a managed image for a specific slot
|
|
77
|
+
*/
|
|
78
|
+
declare function fetchManagedImage(config: ImageApiConfig, slotId: string, pagePath?: string): Promise<{
|
|
79
|
+
image: ManagedImageData | null;
|
|
80
|
+
is_placeholder: boolean;
|
|
81
|
+
}>;
|
|
82
|
+
/**
|
|
83
|
+
* Fetch all managed images for the project
|
|
84
|
+
*/
|
|
85
|
+
declare function fetchManagedImages(config: ImageApiConfig, options?: {
|
|
86
|
+
pagePath?: string;
|
|
87
|
+
category?: string;
|
|
88
|
+
includePlaceholders?: boolean;
|
|
89
|
+
}): Promise<{
|
|
90
|
+
images: ManagedImageData[];
|
|
91
|
+
}>;
|
|
92
|
+
/**
|
|
93
|
+
* List available image files in the project
|
|
94
|
+
*/
|
|
95
|
+
declare function listImageFiles(config: ImageApiConfig, options?: {
|
|
96
|
+
folder?: string;
|
|
97
|
+
search?: string;
|
|
98
|
+
}): Promise<{
|
|
99
|
+
files: ImageFile[];
|
|
100
|
+
folders: string[];
|
|
101
|
+
}>;
|
|
102
|
+
/**
|
|
103
|
+
* Upload a new image
|
|
104
|
+
*/
|
|
105
|
+
declare function uploadImage(config: ImageApiConfig, file: File, options?: {
|
|
106
|
+
slotId?: string;
|
|
107
|
+
pagePath?: string;
|
|
108
|
+
folder?: string;
|
|
109
|
+
altText?: string;
|
|
110
|
+
}): Promise<{
|
|
111
|
+
file: ImageFile;
|
|
112
|
+
image?: ManagedImageData;
|
|
113
|
+
}>;
|
|
114
|
+
/**
|
|
115
|
+
* Assign an existing file to an image slot
|
|
116
|
+
*/
|
|
117
|
+
declare function assignImageToSlot(config: ImageApiConfig, slotId: string, options: {
|
|
118
|
+
fileId?: string;
|
|
119
|
+
externalUrl?: string;
|
|
120
|
+
pagePath?: string;
|
|
121
|
+
altText?: string;
|
|
122
|
+
title?: string;
|
|
123
|
+
caption?: string;
|
|
124
|
+
focalPointX?: number;
|
|
125
|
+
focalPointY?: number;
|
|
126
|
+
aspectRatio?: string;
|
|
127
|
+
}): Promise<{
|
|
128
|
+
image: ManagedImageData;
|
|
129
|
+
}>;
|
|
130
|
+
/**
|
|
131
|
+
* Clear an image from a slot (keeps the file)
|
|
132
|
+
*/
|
|
133
|
+
declare function clearImageSlot(config: ImageApiConfig, slotId: string, pagePath?: string): Promise<{
|
|
134
|
+
success: boolean;
|
|
135
|
+
}>;
|
|
136
|
+
|
|
137
|
+
export { type ImageFile as I, ManagedImage as M, type ManagedImageProps as a, type ManagedImageData as b, fetchManagedImages as c, assignImageToSlot as d, clearImageSlot as e, fetchManagedImage as f, type ImageApiConfig as g, listImageFiles as l, uploadImage as u };
|
|
@@ -1,77 +1,77 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkIYVJGUYX_js = require('./chunk-IYVJGUYX.js');
|
|
4
4
|
require('./chunk-ZSMWDLMK.js');
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
Object.defineProperty(exports, "getABTest", {
|
|
9
9
|
enumerable: true,
|
|
10
|
-
get: function () { return
|
|
10
|
+
get: function () { return chunkIYVJGUYX_js.getABTest; }
|
|
11
11
|
});
|
|
12
12
|
Object.defineProperty(exports, "getContentBlock", {
|
|
13
13
|
enumerable: true,
|
|
14
|
-
get: function () { return
|
|
14
|
+
get: function () { return chunkIYVJGUYX_js.getContentBlock; }
|
|
15
15
|
});
|
|
16
16
|
Object.defineProperty(exports, "getEntities", {
|
|
17
17
|
enumerable: true,
|
|
18
|
-
get: function () { return
|
|
18
|
+
get: function () { return chunkIYVJGUYX_js.getEntities; }
|
|
19
19
|
});
|
|
20
20
|
Object.defineProperty(exports, "getEntityEnhancedSchema", {
|
|
21
21
|
enumerable: true,
|
|
22
|
-
get: function () { return
|
|
22
|
+
get: function () { return chunkIYVJGUYX_js.getEntityEnhancedSchema; }
|
|
23
23
|
});
|
|
24
24
|
Object.defineProperty(exports, "getFAQData", {
|
|
25
25
|
enumerable: true,
|
|
26
|
-
get: function () { return
|
|
26
|
+
get: function () { return chunkIYVJGUYX_js.getFAQData; }
|
|
27
27
|
});
|
|
28
28
|
Object.defineProperty(exports, "getInternalLinks", {
|
|
29
29
|
enumerable: true,
|
|
30
|
-
get: function () { return
|
|
30
|
+
get: function () { return chunkIYVJGUYX_js.getInternalLinks; }
|
|
31
31
|
});
|
|
32
32
|
Object.defineProperty(exports, "getManagedScripts", {
|
|
33
33
|
enumerable: true,
|
|
34
|
-
get: function () { return
|
|
34
|
+
get: function () { return chunkIYVJGUYX_js.getManagedScripts; }
|
|
35
35
|
});
|
|
36
36
|
Object.defineProperty(exports, "getPrimaryEntity", {
|
|
37
37
|
enumerable: true,
|
|
38
|
-
get: function () { return
|
|
38
|
+
get: function () { return chunkIYVJGUYX_js.getPrimaryEntity; }
|
|
39
39
|
});
|
|
40
40
|
Object.defineProperty(exports, "getRedirectData", {
|
|
41
41
|
enumerable: true,
|
|
42
|
-
get: function () { return
|
|
42
|
+
get: function () { return chunkIYVJGUYX_js.getRedirectData; }
|
|
43
43
|
});
|
|
44
44
|
Object.defineProperty(exports, "getRobotsData", {
|
|
45
45
|
enumerable: true,
|
|
46
|
-
get: function () { return
|
|
46
|
+
get: function () { return chunkIYVJGUYX_js.getRobotsData; }
|
|
47
47
|
});
|
|
48
48
|
Object.defineProperty(exports, "getSEOPageData", {
|
|
49
49
|
enumerable: true,
|
|
50
|
-
get: function () { return
|
|
50
|
+
get: function () { return chunkIYVJGUYX_js.getSEOPageData; }
|
|
51
51
|
});
|
|
52
52
|
Object.defineProperty(exports, "getSchemaMarkups", {
|
|
53
53
|
enumerable: true,
|
|
54
|
-
get: function () { return
|
|
54
|
+
get: function () { return chunkIYVJGUYX_js.getSchemaMarkups; }
|
|
55
55
|
});
|
|
56
56
|
Object.defineProperty(exports, "getSitemapEntries", {
|
|
57
57
|
enumerable: true,
|
|
58
|
-
get: function () { return
|
|
58
|
+
get: function () { return chunkIYVJGUYX_js.getSitemapEntries; }
|
|
59
59
|
});
|
|
60
60
|
Object.defineProperty(exports, "getVisibilityScore", {
|
|
61
61
|
enumerable: true,
|
|
62
|
-
get: function () { return
|
|
62
|
+
get: function () { return chunkIYVJGUYX_js.getVisibilityScore; }
|
|
63
63
|
});
|
|
64
64
|
Object.defineProperty(exports, "getVisibilitySummary", {
|
|
65
65
|
enumerable: true,
|
|
66
|
-
get: function () { return
|
|
66
|
+
get: function () { return chunkIYVJGUYX_js.getVisibilitySummary; }
|
|
67
67
|
});
|
|
68
68
|
Object.defineProperty(exports, "recordABImpression", {
|
|
69
69
|
enumerable: true,
|
|
70
|
-
get: function () { return
|
|
70
|
+
get: function () { return chunkIYVJGUYX_js.recordABImpression; }
|
|
71
71
|
});
|
|
72
72
|
Object.defineProperty(exports, "registerSitemap", {
|
|
73
73
|
enumerable: true,
|
|
74
|
-
get: function () { return
|
|
74
|
+
get: function () { return chunkIYVJGUYX_js.registerSitemap; }
|
|
75
75
|
});
|
|
76
|
-
//# sourceMappingURL=api-
|
|
77
|
-
//# sourceMappingURL=api-
|
|
76
|
+
//# sourceMappingURL=api-UBHLAPUG.js.map
|
|
77
|
+
//# sourceMappingURL=api-UBHLAPUG.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"api-UBHLAPUG.js"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { getABTest, getContentBlock, getEntities, getEntityEnhancedSchema, getFAQData, getInternalLinks, getManagedScripts, getPrimaryEntity, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, getVisibilityScore, getVisibilitySummary, recordABImpression, registerSitemap } from './chunk-
|
|
1
|
+
export { getABTest, getContentBlock, getEntities, getEntityEnhancedSchema, getFAQData, getInternalLinks, getManagedScripts, getPrimaryEntity, getRedirectData, getRobotsData, getSEOPageData, getSchemaMarkups, getSitemapEntries, getVisibilityScore, getVisibilitySummary, recordABImpression, registerSitemap } from './chunk-SKHOW2CI.mjs';
|
|
2
2
|
import './chunk-4XPGGLVP.mjs';
|
|
3
|
-
//# sourceMappingURL=api-
|
|
4
|
-
//# sourceMappingURL=api-
|
|
3
|
+
//# sourceMappingURL=api-XNF6Q5HO.mjs.map
|
|
4
|
+
//# sourceMappingURL=api-XNF6Q5HO.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"api-XNF6Q5HO.mjs"}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkIYVJGUYX_js = require('./chunk-IYVJGUYX.js');
|
|
4
4
|
|
|
5
5
|
// src/seo/routing.ts
|
|
6
6
|
async function getRedirect(options) {
|
|
7
7
|
const { projectId, path } = options;
|
|
8
|
-
const redirect = await
|
|
8
|
+
const redirect = await chunkIYVJGUYX_js.getRedirectData(projectId, path);
|
|
9
9
|
if (!redirect) {
|
|
10
10
|
return null;
|
|
11
11
|
}
|
|
@@ -47,7 +47,7 @@ function parseRobotsString(robots) {
|
|
|
47
47
|
}
|
|
48
48
|
async function getRobotsDirective(options) {
|
|
49
49
|
const { projectId, path } = options;
|
|
50
|
-
const robotsString = await
|
|
50
|
+
const robotsString = await chunkIYVJGUYX_js.getRobotsData(projectId, path);
|
|
51
51
|
if (!robotsString) {
|
|
52
52
|
return { index: true, follow: true };
|
|
53
53
|
}
|
|
@@ -55,7 +55,7 @@ async function getRobotsDirective(options) {
|
|
|
55
55
|
}
|
|
56
56
|
async function generateSitemap(options) {
|
|
57
57
|
const { projectId, baseUrl, publishedOnly = true } = options;
|
|
58
|
-
const pages = await
|
|
58
|
+
const pages = await chunkIYVJGUYX_js.getSitemapEntries(projectId, { publishedOnly });
|
|
59
59
|
const normalizedBase = baseUrl.endsWith("/") ? baseUrl.slice(0, -1) : baseUrl;
|
|
60
60
|
return pages.map((page) => ({
|
|
61
61
|
path: page.path,
|
|
@@ -66,7 +66,7 @@ async function generateSitemap(options) {
|
|
|
66
66
|
}));
|
|
67
67
|
}
|
|
68
68
|
async function registerLocalSitemap(options) {
|
|
69
|
-
const { registerSitemap } = await import('./api-
|
|
69
|
+
const { registerSitemap } = await import('./api-UBHLAPUG.js');
|
|
70
70
|
let entries = options.entries || [];
|
|
71
71
|
if (options.autoDiscover && entries.length === 0) {
|
|
72
72
|
try {
|
|
@@ -86,7 +86,10 @@ async function registerLocalSitemap(options) {
|
|
|
86
86
|
return { success: true, created: 0, updated: 0 };
|
|
87
87
|
}
|
|
88
88
|
console.log(`[Uptrade] Registering ${entries.length} sitemap entries...`);
|
|
89
|
-
const result = await registerSitemap(entries
|
|
89
|
+
const result = await registerSitemap(entries, {
|
|
90
|
+
optimize_meta: options.optimize_meta !== false
|
|
91
|
+
// Default to true
|
|
92
|
+
});
|
|
90
93
|
if (result.success) {
|
|
91
94
|
console.log(`[Uptrade] Sitemap registered: ${result.created} new, ${result.updated} updated`);
|
|
92
95
|
}
|
|
@@ -136,5 +139,5 @@ exports.getRedirect = getRedirect;
|
|
|
136
139
|
exports.getRobotsDirective = getRobotsDirective;
|
|
137
140
|
exports.isIndexable = isIndexable;
|
|
138
141
|
exports.registerLocalSitemap = registerLocalSitemap;
|
|
139
|
-
//# sourceMappingURL=chunk-
|
|
140
|
-
//# sourceMappingURL=chunk-
|
|
142
|
+
//# sourceMappingURL=chunk-AWAJEIZS.js.map
|
|
143
|
+
//# sourceMappingURL=chunk-AWAJEIZS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/seo/routing.ts"],"names":["getRedirectData","getRobotsData","getSitemapEntries"],"mappings":"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","file":"chunk-AWAJEIZS.js","sourcesContent":["import { getRedirectData, getRobotsData, getSitemapEntries } from './api'\nimport type { \n GetRedirectOptions, \n RedirectResult, \n GetRobotsOptions, \n RobotsDirective,\n GetSitemapEntriesOptions,\n SitemapEntry \n} from './types'\n\n/**\n * Get redirect for a path if one exists\n * \n * Use in Next.js middleware to handle managed redirects\n * \n * @example\n * ```tsx\n * // middleware.ts\n * import { getRedirect } from '@uptrade/seo'\n * \n * export async function middleware(request) {\n * const redirect = await getRedirect({\n * projectId: process.env.UPTRADE_PROJECT_ID!,\n * path: request.nextUrl.pathname\n * })\n * \n * if (redirect) {\n * return NextResponse.redirect(redirect.destination, redirect.statusCode)\n * }\n * }\n * ```\n */\nexport async function getRedirect(\n options: GetRedirectOptions\n): Promise<RedirectResult | null> {\n const { projectId, path } = options\n\n const redirect = await getRedirectData(projectId, path)\n\n if (!redirect) {\n return null\n }\n\n // Check if expired\n if (redirect.expires_at && new Date(redirect.expires_at) < new Date()) {\n return null\n }\n\n // Determine destination\n const destination = redirect.destination_url || redirect.destination_path\n const isExternal = destination.startsWith('http://') || destination.startsWith('https://')\n\n return {\n destination,\n statusCode: redirect.status_code,\n isExternal,\n }\n}\n\n/**\n * Parse robots directive string into structured object\n */\nfunction parseRobotsString(robots: string): RobotsDirective {\n const directive: RobotsDirective = {\n index: true,\n follow: true,\n }\n\n const parts = robots.toLowerCase().split(',').map(p => p.trim())\n\n for (const part of parts) {\n if (part === 'noindex') directive.index = false\n if (part === 'nofollow') directive.follow = false\n if (part === 'noarchive') directive.noarchive = true\n if (part === 'nosnippet') directive.nosnippet = true\n if (part === 'noimageindex') directive.noimageindex = true\n if (part.startsWith('max-snippet:')) {\n directive.max_snippet = parseInt(part.split(':')[1], 10)\n }\n if (part.startsWith('max-image-preview:')) {\n const value = part.split(':')[1] as 'none' | 'standard' | 'large'\n directive.max_image_preview = value\n }\n if (part.startsWith('max-video-preview:')) {\n directive.max_video_preview = parseInt(part.split(':')[1], 10)\n }\n }\n\n return directive\n}\n\n/**\n * Get robots directive for a page\n * \n * @example\n * ```tsx\n * const robots = await getRobotsDirective({\n * projectId: process.env.UPTRADE_PROJECT_ID!,\n * path: '/private-page'\n * })\n * \n * if (!robots.index) {\n * // Page should not be indexed\n * }\n * ```\n */\nexport async function getRobotsDirective(\n options: GetRobotsOptions\n): Promise<RobotsDirective> {\n const { projectId, path } = options\n\n const robotsString = await getRobotsData(projectId, path)\n\n if (!robotsString) {\n // Default: index and follow\n return { index: true, follow: true }\n }\n\n return parseRobotsString(robotsString)\n}\n\n/**\n * Get sitemap entries for a project\n * \n * Use in sitemap.ts to generate dynamic sitemap\n * \n * @example\n * ```tsx\n * // app/sitemap.ts\n * import { generateSitemap } from '@uptrade/seo'\n * \n * export default async function sitemap() {\n * return generateSitemap({\n * projectId: process.env.UPTRADE_PROJECT_ID!,\n * baseUrl: 'https://example.com',\n * publishedOnly: true\n * })\n * }\n * ```\n */\nexport async function generateSitemap(\n options: GetSitemapEntriesOptions\n): Promise<SitemapEntry[]> {\n const { projectId, baseUrl, publishedOnly = true } = options\n\n const pages = await getSitemapEntries(projectId, { publishedOnly })\n\n const normalizedBase = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl\n\n return pages.map(page => ({\n path: page.path,\n url: `${normalizedBase}${page.path}`,\n lastmod: page.updated_at,\n changefreq: page.sitemap_changefreq || 'weekly',\n priority: page.sitemap_priority || 0.5,\n }))\n}\n\n/**\n * Register local sitemap entries with Uptrade Portal\n * \n * Call this at build time to sync your local routes to seo_pages.\n * This ensures analytics only tracks real pages.\n * \n * After registration, Signal AI will generate optimized meta titles\n * and descriptions for pages that don't have managed meta yet.\n * \n * @example\n * ```ts\n * // scripts/register-sitemap.ts\n * import { registerLocalSitemap } from '@uptrade/seo'\n * \n * // Option 1: Provide entries directly\n * await registerLocalSitemap({\n * entries: [\n * { path: '/', title: 'Home', priority: 1.0 },\n * { path: '/about', title: 'About Us', priority: 0.8 },\n * ]\n * })\n * \n * // Option 2: Auto-discover from Next.js app directory\n * await registerLocalSitemap({ autoDiscover: true })\n * \n * // Option 3: Skip Signal AI meta optimization\n * await registerLocalSitemap({ autoDiscover: true, optimize_meta: false })\n * ```\n */\nexport async function registerLocalSitemap(options: {\n entries?: Array<{\n path: string\n title?: string\n priority?: number\n changefreq?: 'always' | 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly' | 'never'\n }>\n autoDiscover?: boolean\n /** Trigger Signal AI to generate optimized meta titles/descriptions (default: true) */\n optimize_meta?: boolean\n}): Promise<{ \n success: boolean\n created: number\n updated: number\n removed?: number\n meta_optimization?: {\n triggered: boolean\n pages_queued: number\n } | null\n}> {\n const { registerSitemap } = await import('./api')\n \n let entries = options.entries || []\n \n // Auto-discover from Next.js app directory if requested\n if (options.autoDiscover && entries.length === 0) {\n try {\n const fs = await import('fs')\n const path = await import('path')\n \n const appDir = path.join(process.cwd(), 'app')\n if (fs.existsSync(appDir)) {\n entries = discoverNextJsRoutes(appDir, fs, path)\n console.log(`[Uptrade] Auto-discovered ${entries.length} routes from app directory`)\n }\n } catch (error) {\n console.error('[Uptrade] Auto-discovery failed:', error)\n }\n }\n \n if (entries.length === 0) {\n console.warn('[Uptrade] No sitemap entries to register')\n return { success: true, created: 0, updated: 0 }\n }\n \n console.log(`[Uptrade] Registering ${entries.length} sitemap entries...`)\n const result = await registerSitemap(entries, { \n optimize_meta: options.optimize_meta !== false, // Default to true\n })\n \n if (result.success) {\n console.log(`[Uptrade] Sitemap registered: ${result.created} new, ${result.updated} updated`)\n }\n \n return result\n}\n\n/**\n * Discover routes from Next.js app directory\n */\nfunction discoverNextJsRoutes(\n appDir: string,\n fs: typeof import('fs'),\n path: typeof import('path'),\n basePath: string = ''\n): Array<{ path: string; priority: number }> {\n const entries: Array<{ path: string; priority: number }> = []\n \n const items = fs.readdirSync(appDir, { withFileTypes: true })\n \n for (const item of items) {\n // Skip private folders, api routes, and special files\n if (item.name.startsWith('_') || item.name.startsWith('.')) continue\n if (item.name === 'api') continue\n if (item.name === 'node_modules') continue\n \n const itemPath = path.join(appDir, item.name)\n \n if (item.isDirectory()) {\n // Check for page.tsx/page.js in this directory\n const hasPage = fs.existsSync(path.join(itemPath, 'page.tsx')) ||\n fs.existsSync(path.join(itemPath, 'page.js')) ||\n fs.existsSync(path.join(itemPath, 'page.jsx'))\n \n // Handle route groups (parentheses)\n const isRouteGroup = item.name.startsWith('(') && item.name.endsWith(')')\n \n // Handle dynamic segments [slug]\n const isDynamic = item.name.startsWith('[') && item.name.endsWith(']')\n \n let routePath = basePath\n if (!isRouteGroup && !isDynamic) {\n routePath = `${basePath}/${item.name}`\n }\n \n if (hasPage && !isDynamic) {\n const priority = routePath === '' ? 1.0 : 0.8\n entries.push({ path: routePath || '/', priority })\n }\n \n // Recurse into subdirectories (but not dynamic ones)\n if (!isDynamic) {\n const subEntries = discoverNextJsRoutes(itemPath, fs, path, isRouteGroup ? basePath : routePath)\n entries.push(...subEntries)\n }\n }\n }\n \n // Add root if app/page.tsx exists and we're at root\n if (basePath === '') {\n const hasRootPage = fs.existsSync(path.join(appDir, 'page.tsx')) ||\n fs.existsSync(path.join(appDir, 'page.js')) ||\n fs.existsSync(path.join(appDir, 'page.jsx'))\n if (hasRootPage) {\n entries.unshift({ path: '/', priority: 1.0 })\n }\n }\n \n return entries\n}\n\n/**\n * Check if a path should be indexed\n * \n * Quick helper to check indexability without full directive parsing\n */\nexport async function isIndexable(\n projectId: string,\n path: string\n): Promise<boolean> {\n const directive = await getRobotsDirective({ projectId, path })\n return directive.index\n}\n"]}
|