@mailoo/next-core 0.0.0-stage → 1.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,16 @@
1
+ Mailoo Integrator Use License
2
+
3
+ Copyright (c) 2026 Mailoo
4
+
5
+ Permission is granted to use, install, and distribute this software in
6
+ unmodified form, including as a dependency of an application.
7
+
8
+ Modification of this software is not permitted.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
16
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,23 @@
1
- # Temporary Holding Version
1
+ # `@mailoo/next-core`
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Shared Next.js BFF helpers for Mailoo integration modules (`@mailoo/blog`,
4
+ `@mailoo/forms`, `@mailoo/chat`, `@mailoo/images`, `@mailoo/market`).
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ pnpm add @mailoo/next-core
10
+ ```
11
+
12
+ Published on npm as `@mailoo/next-core`.
13
+
14
+ ## Exports
15
+
16
+ - `readMailooIntegrationConfig` / `requireMailooIntegrationConfig` — env-based config
17
+ - `proxyMailooWebhookJsonPost` / `proxyMailooApiGet` — server-side Mailoo API proxy;
18
+ network failure returns HTTP **502** JSON (never throws)
19
+ - `@mailoo/next-core/request-origin` → `getRequestOriginBaseUrl` — absolute origin from request headers (RSC only; keep off the main barrel so client graphs never import `next/headers`)
20
+ - `jsonError` — JSON error Response helper
21
+
22
+ Hosts must treat Mailoo as a feature: check BFF status / Result objects so a
23
+ down API does not 500 the whole site.
package/dist/index.cjs ADDED
@@ -0,0 +1,127 @@
1
+ 'use strict';
2
+
3
+ // src/types.ts
4
+ var defaultMailooLogger = {
5
+ error: (message, ...args) => {
6
+ console.error(message, ...args);
7
+ },
8
+ warn: (message, ...args) => {
9
+ console.warn(message, ...args);
10
+ },
11
+ logException: (error, message) => {
12
+ console.error(message, error);
13
+ }
14
+ };
15
+
16
+ // src/env.ts
17
+ function trimEnv(value) {
18
+ const v = value?.trim();
19
+ return v || void 0;
20
+ }
21
+ function readMailooIntegrationConfig(options) {
22
+ const { prefix, allowApiBaseUrlFallback = false } = options;
23
+ const apiKey = trimEnv(process.env[`${prefix}_API_KEY`]);
24
+ const projectUid = trimEnv(process.env[`${prefix}_PROJECT_UID`]);
25
+ const integrationId = trimEnv(process.env[`${prefix}_ID`]) || trimEnv(process.env[`${prefix}_INTEGRATION_ID`]);
26
+ let apiBase = trimEnv(process.env[`${prefix}_API`]) || (allowApiBaseUrlFallback ? trimEnv(process.env.API_BASE_URL) : void 0);
27
+ if (!apiKey || !projectUid || !integrationId || !apiBase) {
28
+ return null;
29
+ }
30
+ apiBase = apiBase.replace(/\/$/, "");
31
+ return {
32
+ apiBaseUrl: apiBase,
33
+ apiKey,
34
+ projectUid,
35
+ integrationId
36
+ };
37
+ }
38
+ function requireMailooIntegrationConfig(options) {
39
+ const config = readMailooIntegrationConfig(options);
40
+ if (!config) {
41
+ throw new Error(
42
+ options.missingMessage ?? `${options.prefix}_API, ${options.prefix}_API_KEY, ${options.prefix}_PROJECT_UID and ${options.prefix}_ID (or _INTEGRATION_ID) must be set`
43
+ );
44
+ }
45
+ return config;
46
+ }
47
+
48
+ // src/upstream-origin.ts
49
+ function mailooUpstreamOrigin(request) {
50
+ const raw = request.headers.get("origin")?.trim();
51
+ if (!raw) return void 0;
52
+ try {
53
+ const u = new URL(raw);
54
+ if (u.protocol !== "http:" && u.protocol !== "https:") return void 0;
55
+ return u.origin;
56
+ } catch {
57
+ return void 0;
58
+ }
59
+ }
60
+
61
+ // src/proxy-webhook.ts
62
+ function jsonError(body, status) {
63
+ return new Response(JSON.stringify(body), {
64
+ status,
65
+ headers: { "Content-Type": "application/json" }
66
+ });
67
+ }
68
+ var UPSTREAM_FAILED = {
69
+ success: false,
70
+ error: "Upstream request failed",
71
+ message: "Upstream request failed"
72
+ };
73
+ async function proxyMailooWebhookJsonPost(options) {
74
+ const { request, url, apiKey, body } = options;
75
+ const headers = {
76
+ "Content-Type": "application/json",
77
+ "X-API-Key": apiKey
78
+ };
79
+ const origin = mailooUpstreamOrigin(request);
80
+ if (origin) headers.Origin = origin;
81
+ try {
82
+ const response = await fetch(url, {
83
+ method: "POST",
84
+ headers,
85
+ body: JSON.stringify(body)
86
+ });
87
+ const data = await response.json().catch(() => ({}));
88
+ return new Response(JSON.stringify(data), {
89
+ status: response.status,
90
+ headers: { "Content-Type": "application/json" }
91
+ });
92
+ } catch {
93
+ return jsonError(UPSTREAM_FAILED, 502);
94
+ }
95
+ }
96
+ async function proxyMailooApiGet(options) {
97
+ const headers = {
98
+ "Content-Type": "application/json",
99
+ "X-API-Key": options.apiKey
100
+ };
101
+ if (options.origin) {
102
+ headers.Origin = options.origin;
103
+ }
104
+ try {
105
+ const response = await fetch(options.url, {
106
+ method: "GET",
107
+ headers
108
+ });
109
+ const data = await response.json().catch(() => ({}));
110
+ return new Response(JSON.stringify(data), {
111
+ status: response.status,
112
+ headers: { "Content-Type": "application/json" }
113
+ });
114
+ } catch {
115
+ return jsonError(UPSTREAM_FAILED, 502);
116
+ }
117
+ }
118
+
119
+ exports.defaultMailooLogger = defaultMailooLogger;
120
+ exports.jsonError = jsonError;
121
+ exports.mailooUpstreamOrigin = mailooUpstreamOrigin;
122
+ exports.proxyMailooApiGet = proxyMailooApiGet;
123
+ exports.proxyMailooWebhookJsonPost = proxyMailooWebhookJsonPost;
124
+ exports.readMailooIntegrationConfig = readMailooIntegrationConfig;
125
+ exports.requireMailooIntegrationConfig = requireMailooIntegrationConfig;
126
+ //# sourceMappingURL=index.cjs.map
127
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/env.ts","../src/upstream-origin.ts","../src/proxy-webhook.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["/** Common Mailoo integration credentials (server-only). */\nexport type MailooIntegrationConfig = {\n apiBaseUrl: string\n apiKey: string\n projectUid: string\n integrationId: string\n}\n\nexport type MailooLogger = {\n error: (message: string, ...args: unknown[]) => void\n warn?: (message: string, ...args: unknown[]) => void\n logException?: (error: unknown, message: string) => void\n}\n\nexport const defaultMailooLogger: MailooLogger = {\n error: (message, ...args) => {\n console.error(message, ...args)\n },\n warn: (message, ...args) => {\n console.warn(message, ...args)\n },\n logException: (error, message) => {\n console.error(message, error)\n },\n}\n","import type { MailooIntegrationConfig } from './types.js'\n\nfunction trimEnv(value: string | undefined): string | undefined {\n const v = value?.trim()\n return v || undefined\n}\n\n/**\n * Read a Mailoo integration config from env var prefixes.\n * Example prefixes: `MAILOO_BLOG`, `MAILOO_CHAT_INTEGRATION`.\n *\n * Looks for:\n * - `{PREFIX}_API` or `{PREFIX}_API` + fallback `API_BASE_URL`\n * - `{PREFIX}_API_KEY`\n * - `{PREFIX}_PROJECT_UID`\n * - `{PREFIX}_ID` or `{PREFIX}_INTEGRATION_ID`\n */\nexport function readMailooIntegrationConfig(options: {\n prefix: string\n /** When API base is missing, fall back to API_BASE_URL */\n allowApiBaseUrlFallback?: boolean\n}): MailooIntegrationConfig | null {\n const { prefix, allowApiBaseUrlFallback = false } = options\n const apiKey = trimEnv(process.env[`${prefix}_API_KEY`])\n const projectUid = trimEnv(process.env[`${prefix}_PROJECT_UID`])\n const integrationId =\n trimEnv(process.env[`${prefix}_ID`]) ||\n trimEnv(process.env[`${prefix}_INTEGRATION_ID`])\n let apiBase =\n trimEnv(process.env[`${prefix}_API`]) ||\n (allowApiBaseUrlFallback ? trimEnv(process.env.API_BASE_URL) : undefined)\n\n if (!apiKey || !projectUid || !integrationId || !apiBase) {\n return null\n }\n\n apiBase = apiBase.replace(/\\/$/, '')\n return {\n apiBaseUrl: apiBase,\n apiKey,\n projectUid,\n integrationId,\n }\n}\n\n/** Require all four env vars; throw if any missing (fail-fast). */\nexport function requireMailooIntegrationConfig(options: {\n prefix: string\n allowApiBaseUrlFallback?: boolean\n missingMessage?: string\n}): MailooIntegrationConfig {\n const config = readMailooIntegrationConfig(options)\n if (!config) {\n throw new Error(\n options.missingMessage ??\n `${options.prefix}_API, ${options.prefix}_API_KEY, ${options.prefix}_PROJECT_UID and ${options.prefix}_ID (or _INTEGRATION_ID) must be set`\n )\n }\n return config\n}\n","/**\n * Origin to forward from a Next BFF to Mailoo webhook APIs.\n * Never use Referer — path-bearing Referers fail exact allowedOrigins checks.\n * When the browser sends no Origin (typical same-origin GET), omit the header\n * so the API treats the call as server-to-server.\n */\nexport function mailooUpstreamOrigin(\n request: { headers: { get(name: string): string | null } }\n): string | undefined {\n const raw = request.headers.get('origin')?.trim()\n if (!raw) return undefined\n try {\n const u = new URL(raw)\n if (u.protocol !== 'http:' && u.protocol !== 'https:') return undefined\n return u.origin\n } catch {\n return undefined\n }\n}\n","import type { NextRequest } from 'next/server'\nimport { mailooUpstreamOrigin } from './upstream-origin.js'\n\n/** JSON error Response helper. */\nexport function jsonError(body: unknown, status: number): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\nconst UPSTREAM_FAILED = {\n success: false,\n error: 'Upstream request failed',\n message: 'Upstream request failed',\n} as const\n\n/**\n * Forward JSON to a Mailoo webhook URL with server-held API key.\n * Forwards a real browser Origin when present (never Referer).\n * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).\n */\nexport async function proxyMailooWebhookJsonPost(options: {\n request: NextRequest\n url: string\n apiKey: string\n body: unknown\n}): Promise<Response> {\n const { request, url, apiKey, body } = options\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': apiKey,\n }\n const origin = mailooUpstreamOrigin(request)\n if (origin) headers.Origin = origin\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n const data = await response.json().catch(() => ({}))\n return new Response(JSON.stringify(data), {\n status: response.status,\n headers: { 'Content-Type': 'application/json' },\n })\n } catch {\n return jsonError(UPSTREAM_FAILED, 502)\n }\n}\n\n/**\n * Proxy a GET to Mailoo API with X-API-Key.\n * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).\n */\nexport async function proxyMailooApiGet(options: {\n url: string\n apiKey: string\n origin?: string\n}): Promise<Response> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': options.apiKey,\n }\n if (options.origin) {\n headers.Origin = options.origin\n }\n try {\n const response = await fetch(options.url, {\n method: 'GET',\n headers,\n })\n const data = await response.json().catch(() => ({}))\n return new Response(JSON.stringify(data), {\n status: response.status,\n headers: { 'Content-Type': 'application/json' },\n })\n } catch {\n return jsonError(UPSTREAM_FAILED, 502)\n }\n}\n"]}
@@ -0,0 +1,74 @@
1
+ import { NextRequest } from 'next/server';
2
+
3
+ /** Common Mailoo integration credentials (server-only). */
4
+ type MailooIntegrationConfig = {
5
+ apiBaseUrl: string;
6
+ apiKey: string;
7
+ projectUid: string;
8
+ integrationId: string;
9
+ };
10
+ type MailooLogger = {
11
+ error: (message: string, ...args: unknown[]) => void;
12
+ warn?: (message: string, ...args: unknown[]) => void;
13
+ logException?: (error: unknown, message: string) => void;
14
+ };
15
+ declare const defaultMailooLogger: MailooLogger;
16
+
17
+ /**
18
+ * Read a Mailoo integration config from env var prefixes.
19
+ * Example prefixes: `MAILOO_BLOG`, `MAILOO_CHAT_INTEGRATION`.
20
+ *
21
+ * Looks for:
22
+ * - `{PREFIX}_API` or `{PREFIX}_API` + fallback `API_BASE_URL`
23
+ * - `{PREFIX}_API_KEY`
24
+ * - `{PREFIX}_PROJECT_UID`
25
+ * - `{PREFIX}_ID` or `{PREFIX}_INTEGRATION_ID`
26
+ */
27
+ declare function readMailooIntegrationConfig(options: {
28
+ prefix: string;
29
+ /** When API base is missing, fall back to API_BASE_URL */
30
+ allowApiBaseUrlFallback?: boolean;
31
+ }): MailooIntegrationConfig | null;
32
+ /** Require all four env vars; throw if any missing (fail-fast). */
33
+ declare function requireMailooIntegrationConfig(options: {
34
+ prefix: string;
35
+ allowApiBaseUrlFallback?: boolean;
36
+ missingMessage?: string;
37
+ }): MailooIntegrationConfig;
38
+
39
+ /** JSON error Response helper. */
40
+ declare function jsonError(body: unknown, status: number): Response;
41
+ /**
42
+ * Forward JSON to a Mailoo webhook URL with server-held API key.
43
+ * Forwards a real browser Origin when present (never Referer).
44
+ * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).
45
+ */
46
+ declare function proxyMailooWebhookJsonPost(options: {
47
+ request: NextRequest;
48
+ url: string;
49
+ apiKey: string;
50
+ body: unknown;
51
+ }): Promise<Response>;
52
+ /**
53
+ * Proxy a GET to Mailoo API with X-API-Key.
54
+ * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).
55
+ */
56
+ declare function proxyMailooApiGet(options: {
57
+ url: string;
58
+ apiKey: string;
59
+ origin?: string;
60
+ }): Promise<Response>;
61
+
62
+ /**
63
+ * Origin to forward from a Next BFF to Mailoo webhook APIs.
64
+ * Never use Referer — path-bearing Referers fail exact allowedOrigins checks.
65
+ * When the browser sends no Origin (typical same-origin GET), omit the header
66
+ * so the API treats the call as server-to-server.
67
+ */
68
+ declare function mailooUpstreamOrigin(request: {
69
+ headers: {
70
+ get(name: string): string | null;
71
+ };
72
+ }): string | undefined;
73
+
74
+ export { type MailooIntegrationConfig, type MailooLogger, defaultMailooLogger, jsonError, mailooUpstreamOrigin, proxyMailooApiGet, proxyMailooWebhookJsonPost, readMailooIntegrationConfig, requireMailooIntegrationConfig };
@@ -0,0 +1,74 @@
1
+ import { NextRequest } from 'next/server';
2
+
3
+ /** Common Mailoo integration credentials (server-only). */
4
+ type MailooIntegrationConfig = {
5
+ apiBaseUrl: string;
6
+ apiKey: string;
7
+ projectUid: string;
8
+ integrationId: string;
9
+ };
10
+ type MailooLogger = {
11
+ error: (message: string, ...args: unknown[]) => void;
12
+ warn?: (message: string, ...args: unknown[]) => void;
13
+ logException?: (error: unknown, message: string) => void;
14
+ };
15
+ declare const defaultMailooLogger: MailooLogger;
16
+
17
+ /**
18
+ * Read a Mailoo integration config from env var prefixes.
19
+ * Example prefixes: `MAILOO_BLOG`, `MAILOO_CHAT_INTEGRATION`.
20
+ *
21
+ * Looks for:
22
+ * - `{PREFIX}_API` or `{PREFIX}_API` + fallback `API_BASE_URL`
23
+ * - `{PREFIX}_API_KEY`
24
+ * - `{PREFIX}_PROJECT_UID`
25
+ * - `{PREFIX}_ID` or `{PREFIX}_INTEGRATION_ID`
26
+ */
27
+ declare function readMailooIntegrationConfig(options: {
28
+ prefix: string;
29
+ /** When API base is missing, fall back to API_BASE_URL */
30
+ allowApiBaseUrlFallback?: boolean;
31
+ }): MailooIntegrationConfig | null;
32
+ /** Require all four env vars; throw if any missing (fail-fast). */
33
+ declare function requireMailooIntegrationConfig(options: {
34
+ prefix: string;
35
+ allowApiBaseUrlFallback?: boolean;
36
+ missingMessage?: string;
37
+ }): MailooIntegrationConfig;
38
+
39
+ /** JSON error Response helper. */
40
+ declare function jsonError(body: unknown, status: number): Response;
41
+ /**
42
+ * Forward JSON to a Mailoo webhook URL with server-held API key.
43
+ * Forwards a real browser Origin when present (never Referer).
44
+ * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).
45
+ */
46
+ declare function proxyMailooWebhookJsonPost(options: {
47
+ request: NextRequest;
48
+ url: string;
49
+ apiKey: string;
50
+ body: unknown;
51
+ }): Promise<Response>;
52
+ /**
53
+ * Proxy a GET to Mailoo API with X-API-Key.
54
+ * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).
55
+ */
56
+ declare function proxyMailooApiGet(options: {
57
+ url: string;
58
+ apiKey: string;
59
+ origin?: string;
60
+ }): Promise<Response>;
61
+
62
+ /**
63
+ * Origin to forward from a Next BFF to Mailoo webhook APIs.
64
+ * Never use Referer — path-bearing Referers fail exact allowedOrigins checks.
65
+ * When the browser sends no Origin (typical same-origin GET), omit the header
66
+ * so the API treats the call as server-to-server.
67
+ */
68
+ declare function mailooUpstreamOrigin(request: {
69
+ headers: {
70
+ get(name: string): string | null;
71
+ };
72
+ }): string | undefined;
73
+
74
+ export { type MailooIntegrationConfig, type MailooLogger, defaultMailooLogger, jsonError, mailooUpstreamOrigin, proxyMailooApiGet, proxyMailooWebhookJsonPost, readMailooIntegrationConfig, requireMailooIntegrationConfig };
package/dist/index.js ADDED
@@ -0,0 +1,119 @@
1
+ // src/types.ts
2
+ var defaultMailooLogger = {
3
+ error: (message, ...args) => {
4
+ console.error(message, ...args);
5
+ },
6
+ warn: (message, ...args) => {
7
+ console.warn(message, ...args);
8
+ },
9
+ logException: (error, message) => {
10
+ console.error(message, error);
11
+ }
12
+ };
13
+
14
+ // src/env.ts
15
+ function trimEnv(value) {
16
+ const v = value?.trim();
17
+ return v || void 0;
18
+ }
19
+ function readMailooIntegrationConfig(options) {
20
+ const { prefix, allowApiBaseUrlFallback = false } = options;
21
+ const apiKey = trimEnv(process.env[`${prefix}_API_KEY`]);
22
+ const projectUid = trimEnv(process.env[`${prefix}_PROJECT_UID`]);
23
+ const integrationId = trimEnv(process.env[`${prefix}_ID`]) || trimEnv(process.env[`${prefix}_INTEGRATION_ID`]);
24
+ let apiBase = trimEnv(process.env[`${prefix}_API`]) || (allowApiBaseUrlFallback ? trimEnv(process.env.API_BASE_URL) : void 0);
25
+ if (!apiKey || !projectUid || !integrationId || !apiBase) {
26
+ return null;
27
+ }
28
+ apiBase = apiBase.replace(/\/$/, "");
29
+ return {
30
+ apiBaseUrl: apiBase,
31
+ apiKey,
32
+ projectUid,
33
+ integrationId
34
+ };
35
+ }
36
+ function requireMailooIntegrationConfig(options) {
37
+ const config = readMailooIntegrationConfig(options);
38
+ if (!config) {
39
+ throw new Error(
40
+ options.missingMessage ?? `${options.prefix}_API, ${options.prefix}_API_KEY, ${options.prefix}_PROJECT_UID and ${options.prefix}_ID (or _INTEGRATION_ID) must be set`
41
+ );
42
+ }
43
+ return config;
44
+ }
45
+
46
+ // src/upstream-origin.ts
47
+ function mailooUpstreamOrigin(request) {
48
+ const raw = request.headers.get("origin")?.trim();
49
+ if (!raw) return void 0;
50
+ try {
51
+ const u = new URL(raw);
52
+ if (u.protocol !== "http:" && u.protocol !== "https:") return void 0;
53
+ return u.origin;
54
+ } catch {
55
+ return void 0;
56
+ }
57
+ }
58
+
59
+ // src/proxy-webhook.ts
60
+ function jsonError(body, status) {
61
+ return new Response(JSON.stringify(body), {
62
+ status,
63
+ headers: { "Content-Type": "application/json" }
64
+ });
65
+ }
66
+ var UPSTREAM_FAILED = {
67
+ success: false,
68
+ error: "Upstream request failed",
69
+ message: "Upstream request failed"
70
+ };
71
+ async function proxyMailooWebhookJsonPost(options) {
72
+ const { request, url, apiKey, body } = options;
73
+ const headers = {
74
+ "Content-Type": "application/json",
75
+ "X-API-Key": apiKey
76
+ };
77
+ const origin = mailooUpstreamOrigin(request);
78
+ if (origin) headers.Origin = origin;
79
+ try {
80
+ const response = await fetch(url, {
81
+ method: "POST",
82
+ headers,
83
+ body: JSON.stringify(body)
84
+ });
85
+ const data = await response.json().catch(() => ({}));
86
+ return new Response(JSON.stringify(data), {
87
+ status: response.status,
88
+ headers: { "Content-Type": "application/json" }
89
+ });
90
+ } catch {
91
+ return jsonError(UPSTREAM_FAILED, 502);
92
+ }
93
+ }
94
+ async function proxyMailooApiGet(options) {
95
+ const headers = {
96
+ "Content-Type": "application/json",
97
+ "X-API-Key": options.apiKey
98
+ };
99
+ if (options.origin) {
100
+ headers.Origin = options.origin;
101
+ }
102
+ try {
103
+ const response = await fetch(options.url, {
104
+ method: "GET",
105
+ headers
106
+ });
107
+ const data = await response.json().catch(() => ({}));
108
+ return new Response(JSON.stringify(data), {
109
+ status: response.status,
110
+ headers: { "Content-Type": "application/json" }
111
+ });
112
+ } catch {
113
+ return jsonError(UPSTREAM_FAILED, 502);
114
+ }
115
+ }
116
+
117
+ export { defaultMailooLogger, jsonError, mailooUpstreamOrigin, proxyMailooApiGet, proxyMailooWebhookJsonPost, readMailooIntegrationConfig, requireMailooIntegrationConfig };
118
+ //# sourceMappingURL=index.js.map
119
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types.ts","../src/env.ts","../src/upstream-origin.ts","../src/proxy-webhook.ts"],"names":[],"mappings":";AAcO,IAAM,mBAAA,GAAoC;AAAA,EAC/C,KAAA,EAAO,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS;AAC3B,IAAA,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAChC,CAAA;AAAA,EACA,IAAA,EAAM,CAAC,OAAA,EAAA,GAAY,IAAA,KAAS;AAC1B,IAAA,OAAA,CAAQ,IAAA,CAAK,OAAA,EAAS,GAAG,IAAI,CAAA;AAAA,EAC/B,CAAA;AAAA,EACA,YAAA,EAAc,CAAC,KAAA,EAAO,OAAA,KAAY;AAChC,IAAA,OAAA,CAAQ,KAAA,CAAM,SAAS,KAAK,CAAA;AAAA,EAC9B;AACF;;;ACtBA,SAAS,QAAQ,KAAA,EAA+C;AAC9D,EAAA,MAAM,CAAA,GAAI,OAAO,IAAA,EAAK;AACtB,EAAA,OAAO,CAAA,IAAK,MAAA;AACd;AAYO,SAAS,4BAA4B,OAAA,EAIT;AACjC,EAAA,MAAM,EAAE,MAAA,EAAQ,uBAAA,GAA0B,KAAA,EAAM,GAAI,OAAA;AACpD,EAAA,MAAM,SAAS,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA,EAAG,MAAM,UAAU,CAAC,CAAA;AACvD,EAAA,MAAM,aAAa,OAAA,CAAQ,OAAA,CAAQ,IAAI,CAAA,EAAG,MAAM,cAAc,CAAC,CAAA;AAC/D,EAAA,MAAM,aAAA,GACJ,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,CAAA,GAAA,CAAK,CAAC,CAAA,IACnC,QAAQ,OAAA,CAAQ,GAAA,CAAI,CAAA,EAAG,MAAM,iBAAiB,CAAC,CAAA;AACjD,EAAA,IAAI,OAAA,GACF,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,GAAG,MAAM,CAAA,IAAA,CAAM,CAAC,CAAA,KACnC,uBAAA,GAA0B,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,GAAI,MAAA,CAAA;AAEjE,EAAA,IAAI,CAAC,MAAA,IAAU,CAAC,cAAc,CAAC,aAAA,IAAiB,CAAC,OAAA,EAAS;AACxD,IAAA,OAAO,IAAA;AAAA,EACT;AAEA,EAAA,OAAA,GAAU,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA;AACnC,EAAA,OAAO;AAAA,IACL,UAAA,EAAY,OAAA;AAAA,IACZ,MAAA;AAAA,IACA,UAAA;AAAA,IACA;AAAA,GACF;AACF;AAGO,SAAS,+BAA+B,OAAA,EAInB;AAC1B,EAAA,MAAM,MAAA,GAAS,4BAA4B,OAAO,CAAA;AAClD,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,OAAA,CAAQ,cAAA,IACN,CAAA,EAAG,OAAA,CAAQ,MAAM,CAAA,MAAA,EAAS,OAAA,CAAQ,MAAM,CAAA,UAAA,EAAa,OAAA,CAAQ,MAAM,CAAA,iBAAA,EAAoB,QAAQ,MAAM,CAAA,oCAAA;AAAA,KACzG;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;;;ACrDO,SAAS,qBACd,OAAA,EACoB;AACpB,EAAA,MAAM,MAAM,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,GAAG,IAAA,EAAK;AAChD,EAAA,IAAI,CAAC,KAAK,OAAO,MAAA;AACjB,EAAA,IAAI;AACF,IAAA,MAAM,CAAA,GAAI,IAAI,GAAA,CAAI,GAAG,CAAA;AACrB,IAAA,IAAI,EAAE,QAAA,KAAa,OAAA,IAAW,CAAA,CAAE,QAAA,KAAa,UAAU,OAAO,KAAA,CAAA;AAC9D,IAAA,OAAO,CAAA,CAAE,MAAA;AAAA,EACX,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,MAAA;AAAA,EACT;AACF;;;ACdO,SAAS,SAAA,CAAU,MAAe,MAAA,EAA0B;AACjE,EAAA,OAAO,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,IACxC,MAAA;AAAA,IACA,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,GAC/C,CAAA;AACH;AAEA,IAAM,eAAA,GAAkB;AAAA,EACtB,OAAA,EAAS,KAAA;AAAA,EACT,KAAA,EAAO,yBAAA;AAAA,EACP,OAAA,EAAS;AACX,CAAA;AAOA,eAAsB,2BAA2B,OAAA,EAK3B;AACpB,EAAA,MAAM,EAAE,OAAA,EAAS,GAAA,EAAK,MAAA,EAAQ,MAAK,GAAI,OAAA;AACvC,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,cAAA,EAAgB,kBAAA;AAAA,IAChB,WAAA,EAAa;AAAA,GACf;AACA,EAAA,MAAM,MAAA,GAAS,qBAAqB,OAAO,CAAA;AAC3C,EAAA,IAAI,MAAA,UAAgB,MAAA,GAAS,MAAA;AAE7B,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,GAAA,EAAK;AAAA,MAChC,MAAA,EAAQ,MAAA;AAAA,MACR,OAAA;AAAA,MACA,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,IAAI;AAAA,KAC1B,CAAA;AACD,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACnD,IAAA,OAAO,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,MACxC,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,KAC/C,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,SAAA,CAAU,iBAAiB,GAAG,CAAA;AAAA,EACvC;AACF;AAMA,eAAsB,kBAAkB,OAAA,EAIlB;AACpB,EAAA,MAAM,OAAA,GAAkC;AAAA,IACtC,cAAA,EAAgB,kBAAA;AAAA,IAChB,aAAa,OAAA,CAAQ;AAAA,GACvB;AACA,EAAA,IAAI,QAAQ,MAAA,EAAQ;AAClB,IAAA,OAAA,CAAQ,SAAS,OAAA,CAAQ,MAAA;AAAA,EAC3B;AACA,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAAW,MAAM,KAAA,CAAM,OAAA,CAAQ,GAAA,EAAK;AAAA,MACxC,MAAA,EAAQ,KAAA;AAAA,MACR;AAAA,KACD,CAAA;AACD,IAAA,MAAM,IAAA,GAAO,MAAM,QAAA,CAAS,IAAA,GAAO,KAAA,CAAM,OAAO,EAAC,CAAE,CAAA;AACnD,IAAA,OAAO,IAAI,QAAA,CAAS,IAAA,CAAK,SAAA,CAAU,IAAI,CAAA,EAAG;AAAA,MACxC,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,OAAA,EAAS,EAAE,cAAA,EAAgB,kBAAA;AAAmB,KAC/C,CAAA;AAAA,EACH,CAAA,CAAA,MAAQ;AACN,IAAA,OAAO,SAAA,CAAU,iBAAiB,GAAG,CAAA;AAAA,EACvC;AACF","file":"index.js","sourcesContent":["/** Common Mailoo integration credentials (server-only). */\nexport type MailooIntegrationConfig = {\n apiBaseUrl: string\n apiKey: string\n projectUid: string\n integrationId: string\n}\n\nexport type MailooLogger = {\n error: (message: string, ...args: unknown[]) => void\n warn?: (message: string, ...args: unknown[]) => void\n logException?: (error: unknown, message: string) => void\n}\n\nexport const defaultMailooLogger: MailooLogger = {\n error: (message, ...args) => {\n console.error(message, ...args)\n },\n warn: (message, ...args) => {\n console.warn(message, ...args)\n },\n logException: (error, message) => {\n console.error(message, error)\n },\n}\n","import type { MailooIntegrationConfig } from './types.js'\n\nfunction trimEnv(value: string | undefined): string | undefined {\n const v = value?.trim()\n return v || undefined\n}\n\n/**\n * Read a Mailoo integration config from env var prefixes.\n * Example prefixes: `MAILOO_BLOG`, `MAILOO_CHAT_INTEGRATION`.\n *\n * Looks for:\n * - `{PREFIX}_API` or `{PREFIX}_API` + fallback `API_BASE_URL`\n * - `{PREFIX}_API_KEY`\n * - `{PREFIX}_PROJECT_UID`\n * - `{PREFIX}_ID` or `{PREFIX}_INTEGRATION_ID`\n */\nexport function readMailooIntegrationConfig(options: {\n prefix: string\n /** When API base is missing, fall back to API_BASE_URL */\n allowApiBaseUrlFallback?: boolean\n}): MailooIntegrationConfig | null {\n const { prefix, allowApiBaseUrlFallback = false } = options\n const apiKey = trimEnv(process.env[`${prefix}_API_KEY`])\n const projectUid = trimEnv(process.env[`${prefix}_PROJECT_UID`])\n const integrationId =\n trimEnv(process.env[`${prefix}_ID`]) ||\n trimEnv(process.env[`${prefix}_INTEGRATION_ID`])\n let apiBase =\n trimEnv(process.env[`${prefix}_API`]) ||\n (allowApiBaseUrlFallback ? trimEnv(process.env.API_BASE_URL) : undefined)\n\n if (!apiKey || !projectUid || !integrationId || !apiBase) {\n return null\n }\n\n apiBase = apiBase.replace(/\\/$/, '')\n return {\n apiBaseUrl: apiBase,\n apiKey,\n projectUid,\n integrationId,\n }\n}\n\n/** Require all four env vars; throw if any missing (fail-fast). */\nexport function requireMailooIntegrationConfig(options: {\n prefix: string\n allowApiBaseUrlFallback?: boolean\n missingMessage?: string\n}): MailooIntegrationConfig {\n const config = readMailooIntegrationConfig(options)\n if (!config) {\n throw new Error(\n options.missingMessage ??\n `${options.prefix}_API, ${options.prefix}_API_KEY, ${options.prefix}_PROJECT_UID and ${options.prefix}_ID (or _INTEGRATION_ID) must be set`\n )\n }\n return config\n}\n","/**\n * Origin to forward from a Next BFF to Mailoo webhook APIs.\n * Never use Referer — path-bearing Referers fail exact allowedOrigins checks.\n * When the browser sends no Origin (typical same-origin GET), omit the header\n * so the API treats the call as server-to-server.\n */\nexport function mailooUpstreamOrigin(\n request: { headers: { get(name: string): string | null } }\n): string | undefined {\n const raw = request.headers.get('origin')?.trim()\n if (!raw) return undefined\n try {\n const u = new URL(raw)\n if (u.protocol !== 'http:' && u.protocol !== 'https:') return undefined\n return u.origin\n } catch {\n return undefined\n }\n}\n","import type { NextRequest } from 'next/server'\nimport { mailooUpstreamOrigin } from './upstream-origin.js'\n\n/** JSON error Response helper. */\nexport function jsonError(body: unknown, status: number): Response {\n return new Response(JSON.stringify(body), {\n status,\n headers: { 'Content-Type': 'application/json' },\n })\n}\n\nconst UPSTREAM_FAILED = {\n success: false,\n error: 'Upstream request failed',\n message: 'Upstream request failed',\n} as const\n\n/**\n * Forward JSON to a Mailoo webhook URL with server-held API key.\n * Forwards a real browser Origin when present (never Referer).\n * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).\n */\nexport async function proxyMailooWebhookJsonPost(options: {\n request: NextRequest\n url: string\n apiKey: string\n body: unknown\n}): Promise<Response> {\n const { request, url, apiKey, body } = options\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': apiKey,\n }\n const origin = mailooUpstreamOrigin(request)\n if (origin) headers.Origin = origin\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n const data = await response.json().catch(() => ({}))\n return new Response(JSON.stringify(data), {\n status: response.status,\n headers: { 'Content-Type': 'application/json' },\n })\n } catch {\n return jsonError(UPSTREAM_FAILED, 502)\n }\n}\n\n/**\n * Proxy a GET to Mailoo API with X-API-Key.\n * Network / non-JSON upstream failures return HTTP 502 JSON (never throw).\n */\nexport async function proxyMailooApiGet(options: {\n url: string\n apiKey: string\n origin?: string\n}): Promise<Response> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'X-API-Key': options.apiKey,\n }\n if (options.origin) {\n headers.Origin = options.origin\n }\n try {\n const response = await fetch(options.url, {\n method: 'GET',\n headers,\n })\n const data = await response.json().catch(() => ({}))\n return new Response(JSON.stringify(data), {\n status: response.status,\n headers: { 'Content-Type': 'application/json' },\n })\n } catch {\n return jsonError(UPSTREAM_FAILED, 502)\n }\n}\n"]}
@@ -0,0 +1,18 @@
1
+ 'use strict';
2
+
3
+ var headers = require('next/headers');
4
+
5
+ // src/request-origin.ts
6
+ async function getRequestOriginBaseUrl() {
7
+ const headersList = await headers.headers();
8
+ const host = headersList.get("host");
9
+ if (!host) {
10
+ throw new Error("Host header is required to resolve request origin");
11
+ }
12
+ const proto = headersList.get("x-forwarded-proto") || "http";
13
+ return `${proto}://${host}`;
14
+ }
15
+
16
+ exports.getRequestOriginBaseUrl = getRequestOriginBaseUrl;
17
+ //# sourceMappingURL=request-origin.cjs.map
18
+ //# sourceMappingURL=request-origin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/request-origin.ts"],"names":["headers"],"mappings":";;;;;AAMA,eAAsB,uBAAA,GAA2C;AAC/D,EAAA,MAAM,WAAA,GAAc,MAAMA,eAAA,EAAQ;AAClC,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,MAAM,CAAA;AACnC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACrE;AACA,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,GAAA,CAAI,mBAAmB,CAAA,IAAK,MAAA;AACtD,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA;AAC3B","file":"request-origin.cjs","sourcesContent":["import { headers } from 'next/headers'\n\n/**\n * Build an absolute same-origin base URL from Next.js request headers.\n * Used by RSC/server helpers that fetch the app's own BFF routes.\n */\nexport async function getRequestOriginBaseUrl(): Promise<string> {\n const headersList = await headers()\n const host = headersList.get('host')\n if (!host) {\n throw new Error('Host header is required to resolve request origin')\n }\n const proto = headersList.get('x-forwarded-proto') || 'http'\n return `${proto}://${host}`\n}\n"]}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Build an absolute same-origin base URL from Next.js request headers.
3
+ * Used by RSC/server helpers that fetch the app's own BFF routes.
4
+ */
5
+ declare function getRequestOriginBaseUrl(): Promise<string>;
6
+
7
+ export { getRequestOriginBaseUrl };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Build an absolute same-origin base URL from Next.js request headers.
3
+ * Used by RSC/server helpers that fetch the app's own BFF routes.
4
+ */
5
+ declare function getRequestOriginBaseUrl(): Promise<string>;
6
+
7
+ export { getRequestOriginBaseUrl };
@@ -0,0 +1,16 @@
1
+ import { headers } from 'next/headers';
2
+
3
+ // src/request-origin.ts
4
+ async function getRequestOriginBaseUrl() {
5
+ const headersList = await headers();
6
+ const host = headersList.get("host");
7
+ if (!host) {
8
+ throw new Error("Host header is required to resolve request origin");
9
+ }
10
+ const proto = headersList.get("x-forwarded-proto") || "http";
11
+ return `${proto}://${host}`;
12
+ }
13
+
14
+ export { getRequestOriginBaseUrl };
15
+ //# sourceMappingURL=request-origin.js.map
16
+ //# sourceMappingURL=request-origin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/request-origin.ts"],"names":[],"mappings":";;;AAMA,eAAsB,uBAAA,GAA2C;AAC/D,EAAA,MAAM,WAAA,GAAc,MAAM,OAAA,EAAQ;AAClC,EAAA,MAAM,IAAA,GAAO,WAAA,CAAY,GAAA,CAAI,MAAM,CAAA;AACnC,EAAA,IAAI,CAAC,IAAA,EAAM;AACT,IAAA,MAAM,IAAI,MAAM,mDAAmD,CAAA;AAAA,EACrE;AACA,EAAA,MAAM,KAAA,GAAQ,WAAA,CAAY,GAAA,CAAI,mBAAmB,CAAA,IAAK,MAAA;AACtD,EAAA,OAAO,CAAA,EAAG,KAAK,CAAA,GAAA,EAAM,IAAI,CAAA,CAAA;AAC3B","file":"request-origin.js","sourcesContent":["import { headers } from 'next/headers'\n\n/**\n * Build an absolute same-origin base URL from Next.js request headers.\n * Used by RSC/server helpers that fetch the app's own BFF routes.\n */\nexport async function getRequestOriginBaseUrl(): Promise<string> {\n const headersList = await headers()\n const host = headersList.get('host')\n if (!host) {\n throw new Error('Host header is required to resolve request origin')\n }\n const proto = headersList.get('x-forwarded-proto') || 'http'\n return `${proto}://${host}`\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,56 @@
1
1
  {
2
2
  "name": "@mailoo/next-core",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.33.0",
4
+ "description": "Shared Next.js BFF helpers for Mailoo integration modules",
5
+ "license": "LicenseRef-Mailoo-NoModification",
6
+ "homepage": "https://mailoo.app/en/support/docs/integrations/nextjs-packages",
7
+ "keywords": [
8
+ "mailoo",
9
+ "nextjs",
10
+ "next-core"
11
+ ],
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "type": "module",
16
+ "main": "./dist/index.cjs",
17
+ "module": "./dist/index.js",
18
+ "types": "./dist/index.d.ts",
19
+ "exports": {
20
+ ".": {
21
+ "types": "./dist/index.d.ts",
22
+ "import": "./dist/index.js",
23
+ "require": "./dist/index.cjs"
24
+ },
25
+ "./request-origin": {
26
+ "types": "./dist/request-origin.d.ts",
27
+ "import": "./dist/request-origin.js",
28
+ "require": "./dist/request-origin.cjs"
29
+ }
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "README.md",
34
+ "LICENSE"
35
+ ],
36
+ "peerDependencies": {
37
+ "next": ">=16.3.4"
38
+ },
39
+ "devDependencies": {
40
+ "@types/node": "^25.9.5",
41
+ "next": "^16.3.4",
42
+ "tsup": "^8.5.1",
43
+ "typescript": "^5.9.3",
44
+ "vitest": "^4.1.11"
45
+ },
46
+ "engines": {
47
+ "node": ">=20.20.2"
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "clean": "rm -rf dist .turbo",
52
+ "dev": "tsup --watch",
53
+ "test": "vitest run",
54
+ "type-check": "tsc --noEmit"
55
+ }
6
56
  }