sanity-plugin-seofields 1.7.0 → 1.9.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/README.md +440 -29
- package/dist/SchemaOrgJsonLdPreview-DJLkIPq4.d.cts +78 -0
- package/dist/SchemaOrgJsonLdPreview-DJLkIPq4.d.ts +78 -0
- package/dist/SeoHealthTool-2COI27KI.cjs +8 -0
- package/dist/SeoHealthTool-2COI27KI.cjs.map +1 -0
- package/dist/SeoHealthTool-CWI3KB2V.js +8 -0
- package/dist/SeoHealthTool-CWI3KB2V.js.map +1 -0
- package/dist/{SeoPreview-WYH7NYNM.cjs → SeoPreview-LMZAWWOE.cjs} +35 -38
- package/dist/SeoPreview-LMZAWWOE.cjs.map +1 -0
- package/dist/{SeoPreview-KEGGQSPJ.js → SeoPreview-UNQBKTQO.js} +14 -11
- package/dist/SeoPreview-UNQBKTQO.js.map +1 -0
- package/dist/chunk-3OK3S2F7.cjs +673 -0
- package/dist/chunk-3OK3S2F7.cjs.map +1 -0
- package/dist/{chunk-GWPOJSGW.cjs → chunk-5XTQRILL.cjs} +1022 -307
- package/dist/chunk-5XTQRILL.cjs.map +1 -0
- package/dist/{chunk-2NMEKWO5.js → chunk-7N4MLTMR.js} +8 -15
- package/dist/chunk-7N4MLTMR.js.map +1 -0
- package/dist/{chunk-S367Y35J.cjs → chunk-A57XNQC7.cjs} +9 -20
- package/dist/chunk-A57XNQC7.cjs.map +1 -0
- package/dist/chunk-BWLJDK5J.js +624 -0
- package/dist/chunk-BWLJDK5J.js.map +1 -0
- package/dist/chunk-FUUWBQE2.cjs +195 -0
- package/dist/chunk-FUUWBQE2.cjs.map +1 -0
- package/dist/{chunk-ZBHLMQTS.cjs → chunk-HHO2AKAP.js} +44 -17
- package/dist/chunk-HHO2AKAP.js.map +1 -0
- package/dist/chunk-KIEO6QG3.js +195 -0
- package/dist/chunk-KIEO6QG3.js.map +1 -0
- package/dist/chunk-R2U7JF7U.cjs +624 -0
- package/dist/chunk-R2U7JF7U.cjs.map +1 -0
- package/dist/{chunk-HRKRV2X7.js → chunk-XZKQWV2H.js} +974 -148
- package/dist/chunk-XZKQWV2H.js.map +1 -0
- package/dist/{chunk-HDZZQCH7.js → chunk-Y46ACXM4.cjs} +45 -5
- package/dist/chunk-Y46ACXM4.cjs.map +1 -0
- package/dist/chunk-Z5AOUU4H.js +673 -0
- package/dist/chunk-Z5AOUU4H.js.map +1 -0
- package/dist/cli.js +27 -27
- package/dist/{component-DQ4KuQQD.d.ts → component-CjT1hvxh.d.ts} +3 -27
- package/dist/{component-D1sBm6ts.d.cts → component-WYh0z8as.d.cts} +3 -27
- package/dist/define-cli.cjs +2 -4
- package/dist/define-cli.cjs.map +1 -1
- package/dist/define-cli.js +4 -4
- package/dist/define-cli.js.map +1 -1
- package/dist/head.cjs +14 -0
- package/dist/head.cjs.map +1 -0
- package/dist/head.d.cts +254 -0
- package/dist/head.d.ts +254 -0
- package/dist/head.js +14 -0
- package/dist/head.js.map +1 -0
- package/dist/index.cjs +1797 -230
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -598
- package/dist/index.d.ts +11 -598
- package/dist/index.js +1777 -197
- package/dist/index.js.map +1 -1
- package/dist/next.cjs +210 -447
- package/dist/next.cjs.map +1 -1
- package/dist/next.d.cts +8 -200
- package/dist/next.d.ts +8 -200
- package/dist/next.js +200 -124
- package/dist/next.js.map +1 -1
- package/dist/plugin-DQdThyxG.d.ts +449 -0
- package/dist/plugin-DoGeZP79.d.cts +449 -0
- package/dist/schema/next.cjs +173 -319
- package/dist/schema/next.cjs.map +1 -1
- package/dist/schema/next.d.cts +4 -4
- package/dist/schema/next.d.ts +4 -4
- package/dist/schema/next.js +172 -8
- package/dist/schema/next.js.map +1 -1
- package/dist/schema.cjs +390 -489
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +26 -16
- package/dist/schema.d.ts +26 -16
- package/dist/schema.js +236 -13
- package/dist/schema.js.map +1 -1
- package/dist/server.cjs +149 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +102 -0
- package/dist/server.d.ts +102 -0
- package/dist/server.js +149 -0
- package/dist/server.js.map +1 -0
- package/dist/{types-CeBULNFF.d.ts → types-BAdN1RMu.d.ts} +2 -2
- package/dist/{types-_wBLg6RV.d.cts → types-C5i3KMgs.d.cts} +2 -2
- package/dist/{types-9_wbCIi9.d.ts → types-DP-DiW6f.d.cts} +29 -2
- package/dist/{types-Bb49oRBV.d.cts → types-DRLUGLtX.d.ts} +29 -2
- package/dist/{types-B91ena4g.d.cts → types-DxlPXihz.d.cts} +8 -1
- package/dist/{types-B91ena4g.d.ts → types-DxlPXihz.d.ts} +8 -1
- package/package.json +25 -3
- package/dist/SeoHealthDashboard-IP5BJ322.cjs +0 -10
- package/dist/SeoHealthDashboard-IP5BJ322.cjs.map +0 -1
- package/dist/SeoHealthDashboard-PTUEVYZL.js +0 -4
- package/dist/SeoHealthDashboard-PTUEVYZL.js.map +0 -1
- package/dist/SeoHealthTool-CZZRMWQK.cjs +0 -14
- package/dist/SeoHealthTool-CZZRMWQK.cjs.map +0 -1
- package/dist/SeoHealthTool-IULT4G25.js +0 -12
- package/dist/SeoHealthTool-IULT4G25.js.map +0 -1
- package/dist/SeoPreview-KEGGQSPJ.js.map +0 -1
- package/dist/SeoPreview-WYH7NYNM.cjs.map +0 -1
- package/dist/chunk-2NMEKWO5.js.map +0 -1
- package/dist/chunk-5YRH47VQ.cjs +0 -2167
- package/dist/chunk-5YRH47VQ.cjs.map +0 -1
- package/dist/chunk-ARELX3GK.cjs +0 -689
- package/dist/chunk-ARELX3GK.cjs.map +0 -1
- package/dist/chunk-AW7OKBQQ.js +0 -2161
- package/dist/chunk-AW7OKBQQ.js.map +0 -1
- package/dist/chunk-FONJYVF2.js +0 -610
- package/dist/chunk-FONJYVF2.js.map +0 -1
- package/dist/chunk-GWPOJSGW.cjs.map +0 -1
- package/dist/chunk-HDZZQCH7.js.map +0 -1
- package/dist/chunk-HRKRV2X7.js.map +0 -1
- package/dist/chunk-S367Y35J.cjs.map +0 -1
- package/dist/chunk-ZBHLMQTS.cjs.map +0 -1
package/dist/server.cjs
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true});
|
|
2
|
+
|
|
3
|
+
var _chunk3OK3S2F7cjs = require('./chunk-3OK3S2F7.cjs');
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
var _chunkA57XNQC7cjs = require('./chunk-A57XNQC7.cjs');
|
|
9
|
+
|
|
10
|
+
// src/server/aiHandler.ts
|
|
11
|
+
function isValidBody(body) {
|
|
12
|
+
if (!body || typeof body !== "object") return false;
|
|
13
|
+
const { field, content } = body;
|
|
14
|
+
return typeof field === "string" && typeof content === "string";
|
|
15
|
+
}
|
|
16
|
+
function createSeoAiHandler(config) {
|
|
17
|
+
return async function handleSeoAiRequest(body) {
|
|
18
|
+
if (!isValidBody(body)) {
|
|
19
|
+
throw new Error('Invalid request body: "field" and "content" are required.');
|
|
20
|
+
}
|
|
21
|
+
const { field, content, focusKeyword = "", keywords = [], meta, industry, licenseKey } = body;
|
|
22
|
+
const mergedConfig = _chunkA57XNQC7cjs.__spreadProps.call(void 0, _chunkA57XNQC7cjs.__spreadValues.call(void 0, {}, config), {
|
|
23
|
+
industry: industry != null ? industry : config.industry,
|
|
24
|
+
_licenseKey: licenseKey != null ? licenseKey : config._licenseKey
|
|
25
|
+
});
|
|
26
|
+
const result = await _chunk3OK3S2F7cjs.generateSeoText.call(void 0, field, content, focusKeyword, keywords, {
|
|
27
|
+
config: mergedConfig,
|
|
28
|
+
meta
|
|
29
|
+
});
|
|
30
|
+
return { result };
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/server/adapters/express.ts
|
|
35
|
+
function createExpressHandler(config, options = {}) {
|
|
36
|
+
const handle = createSeoAiHandler(config);
|
|
37
|
+
return async function seoAiExpressHandler(req, res) {
|
|
38
|
+
if (options.cors) res.setHeader("Access-Control-Allow-Origin", options.cors);
|
|
39
|
+
if (req.method === "OPTIONS") {
|
|
40
|
+
res.status(204).end();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (req.method !== "POST") {
|
|
44
|
+
res.status(405).json({ error: "Method not allowed" });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const result = await handle(req.body);
|
|
49
|
+
res.status(200).json(result);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
const message = err instanceof Error ? err.message : "AI generation failed.";
|
|
52
|
+
res.status(500).json({ error: message });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/server/adapters/fetch.ts
|
|
58
|
+
function corsHeaders(options) {
|
|
59
|
+
return options.cors ? { "Access-Control-Allow-Origin": options.cors } : {};
|
|
60
|
+
}
|
|
61
|
+
function createFetchHandler(config, options = {}) {
|
|
62
|
+
const handle = createSeoAiHandler(config);
|
|
63
|
+
const headers = _chunkA57XNQC7cjs.__spreadValues.call(void 0, { "Content-Type": "application/json" }, corsHeaders(options));
|
|
64
|
+
return async function seoAiFetchHandler(request) {
|
|
65
|
+
if (request.method === "OPTIONS") {
|
|
66
|
+
return new Response(null, {
|
|
67
|
+
status: 204,
|
|
68
|
+
headers: _chunkA57XNQC7cjs.__spreadProps.call(void 0, _chunkA57XNQC7cjs.__spreadValues.call(void 0, {}, headers), {
|
|
69
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
70
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (request.method !== "POST") {
|
|
75
|
+
return new Response(JSON.stringify({ error: "Method not allowed" }), { status: 405, headers });
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const body = await request.json();
|
|
79
|
+
const result = await handle(body);
|
|
80
|
+
return new Response(JSON.stringify(result), { status: 200, headers });
|
|
81
|
+
} catch (err) {
|
|
82
|
+
const message = err instanceof Error ? err.message : "AI generation failed.";
|
|
83
|
+
return new Response(JSON.stringify({ error: message }), { status: 500, headers });
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/server/adapters/nextjs.ts
|
|
89
|
+
function createNextRouteHandler(config, options) {
|
|
90
|
+
const handler = createFetchHandler(config, options);
|
|
91
|
+
return { POST: handler, OPTIONS: handler };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/server/adapters/node.ts
|
|
95
|
+
async function readJsonBody(req) {
|
|
96
|
+
const chunks = [];
|
|
97
|
+
try {
|
|
98
|
+
for (var iter = _chunkA57XNQC7cjs.__forAwait.call(void 0, req), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
99
|
+
const chunk = temp.value;
|
|
100
|
+
chunks.push(chunk);
|
|
101
|
+
}
|
|
102
|
+
} catch (temp) {
|
|
103
|
+
error = [temp];
|
|
104
|
+
} finally {
|
|
105
|
+
try {
|
|
106
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
107
|
+
} finally {
|
|
108
|
+
if (error)
|
|
109
|
+
throw error[0];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
113
|
+
return raw ? JSON.parse(raw) : {};
|
|
114
|
+
}
|
|
115
|
+
function createNodeHandler(config, options = {}) {
|
|
116
|
+
const handle = createSeoAiHandler(config);
|
|
117
|
+
return async function seoAiNodeHandler(req, res) {
|
|
118
|
+
if (options.cors) res.setHeader("Access-Control-Allow-Origin", options.cors);
|
|
119
|
+
res.setHeader("Content-Type", "application/json");
|
|
120
|
+
if (req.method === "OPTIONS") {
|
|
121
|
+
res.writeHead(204);
|
|
122
|
+
res.end();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (req.method !== "POST") {
|
|
126
|
+
res.writeHead(405);
|
|
127
|
+
res.end(JSON.stringify({ error: "Method not allowed" }));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const body = await readJsonBody(req);
|
|
132
|
+
const result = await handle(body);
|
|
133
|
+
res.writeHead(200);
|
|
134
|
+
res.end(JSON.stringify(result));
|
|
135
|
+
} catch (err) {
|
|
136
|
+
const message = err instanceof Error ? err.message : "AI generation failed.";
|
|
137
|
+
res.writeHead(500);
|
|
138
|
+
res.end(JSON.stringify({ error: message }));
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
exports.createExpressHandler = createExpressHandler; exports.createFetchHandler = createFetchHandler; exports.createNextRouteHandler = createNextRouteHandler; exports.createNodeHandler = createNodeHandler; exports.createSeoAiHandler = createSeoAiHandler;
|
|
149
|
+
//# sourceMappingURL=server.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/server.cjs","../src/server/aiHandler.ts","../src/server/adapters/express.ts","../src/server/adapters/fetch.ts","../src/server/adapters/nextjs.ts","../src/server/adapters/node.ts"],"names":[],"mappings":"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","file":"/Users/hardik/GITHUB/sanity-plugin-seofields/npm/dist/server.cjs","sourcesContent":[null,"import type {AiConfig, AiIndustry} from '../plugin'\nimport {generateSeoText} from '../utils/seoContentGen'\nimport type {MetaContext, SeoGenField} from '../utils/seoPrompts'\n\nexport interface SeoAiRequestBody {\n field: SeoGenField\n content: string\n focusKeyword?: string\n keywords?: string[]\n meta?: MetaContext\n /** Industry chosen in the Studio's `ai.industry` config — forwarded so proxy mode matches direct-provider mode. */\n industry?: AiIndustry\n /** License key forwarded from the Studio's `ai._licenseKey` — determines which prompt pool proxy mode uses. */\n licenseKey?: string\n}\n\nexport interface SeoAiHandler {\n (body: SeoAiRequestBody): Promise<{result: string}>\n}\n\nfunction isValidBody(body: unknown): body is SeoAiRequestBody {\n if (!body || typeof body !== 'object') return false\n const {field, content} = body as Record<string, unknown>\n return typeof field === 'string' && typeof content === 'string'\n}\n\n/**\n * Runs the full SEO text generation pipeline (prompting, retries, validation) server-side using\n * a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with\n * `endpoint` in the Studio's `ai` config, and one of the framework adapters in\n * `sanity-plugin-seofields/server` to expose it over HTTP.\n */\nexport function createSeoAiHandler(config: AiConfig): SeoAiHandler {\n return async function handleSeoAiRequest(body: SeoAiRequestBody): Promise<{result: string}> {\n if (!isValidBody(body)) {\n throw new Error('Invalid request body: \"field\" and \"content\" are required.')\n }\n\n const {field, content, focusKeyword = '', keywords = [], meta, industry, licenseKey} = body\n const mergedConfig: AiConfig = {\n ...config,\n industry: industry ?? config.industry,\n _licenseKey: licenseKey ?? config._licenseKey,\n }\n const result = await generateSeoText(field, content, focusKeyword, keywords, {\n config: mergedConfig,\n meta,\n })\n return {result}\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\n// Duck-typed instead of importing `express` types, so the package has no dependency on Express.\nexport interface MinimalRequest {\n method?: string\n body?: unknown\n}\n\nexport interface MinimalResponse {\n status(code: number): MinimalResponse\n json(body: unknown): void\n setHeader(name: string, value: string): void\n end(): void\n}\n\nexport interface ExpressAdapterOptions {\n cors?: string\n}\n\n/**\n * Express (or Express-compatible) request handler. Requires a JSON body parser\n * (e.g. `app.use(express.json())`) mounted before this route.\n *\n * @example\n * import { createExpressHandler } from 'sanity-plugin-seofields/server'\n * app.post('/api/seo-ai', createExpressHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY }))\n */\nexport function createExpressHandler(\n config: AiConfig,\n options: ExpressAdapterOptions = {},\n): (req: MinimalRequest, res: MinimalResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiExpressHandler(\n req: MinimalRequest,\n res: MinimalResponse,\n ): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n\n if (req.method === 'OPTIONS') {\n res.status(204).end()\n return\n }\n\n if (req.method !== 'POST') {\n res.status(405).json({error: 'Method not allowed'})\n return\n }\n\n try {\n const result = await handle(req.body as SeoAiRequestBody)\n res.status(200).json(result)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.status(500).json({error: message})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface FetchAdapterOptions {\n /** Origin allowed to call this endpoint. Only needed when the proxy is deployed on a\n * different origin than the Studio (same-app routes don't hit CORS at all). */\n cors?: string\n}\n\nfunction corsHeaders(options: FetchAdapterOptions): Record<string, string> {\n return options.cors ? {'Access-Control-Allow-Origin': options.cors} : {}\n}\n\n/**\n * Standard `Request -> Response` handler. Works as-is for Next.js App Router route handlers,\n * Cloudflare Workers, Deno, Bun, Remix, and SvelteKit — anything built on the Fetch API.\n */\nexport function createFetchHandler(\n config: AiConfig,\n options: FetchAdapterOptions = {},\n): (request: Request) => Promise<Response> {\n const handle = createSeoAiHandler(config)\n const headers = {'Content-Type': 'application/json', ...corsHeaders(options)}\n\n return async function seoAiFetchHandler(request: Request): Promise<Response> {\n if (request.method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: {\n ...headers,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n },\n })\n }\n\n if (request.method !== 'POST') {\n return new Response(JSON.stringify({error: 'Method not allowed'}), {status: 405, headers})\n }\n\n try {\n const body = (await request.json()) as SeoAiRequestBody\n const result = await handle(body)\n return new Response(JSON.stringify(result), {status: 200, headers})\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n return new Response(JSON.stringify({error: message}), {status: 500, headers})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createFetchHandler, type FetchAdapterOptions} from './fetch'\n\n/**\n * Next.js App Router route handler.\n *\n * @example\n * // app/api/seo-ai/route.ts\n * import { createNextRouteHandler } from 'sanity-plugin-seofields/server'\n *\n * export const { POST, OPTIONS } = createNextRouteHandler({\n * provider: 'openai',\n * apiKey: process.env.OPENAI_API_KEY,\n * })\n */\nexport function createNextRouteHandler(\n config: AiConfig,\n options?: FetchAdapterOptions,\n): {\n POST: (request: Request) => Promise<Response>\n OPTIONS: (request: Request) => Promise<Response>\n} {\n const handler = createFetchHandler(config, options)\n return {POST: handler, OPTIONS: handler}\n}\n","import type {IncomingMessage, ServerResponse} from 'node:http'\n\nimport type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface NodeAdapterOptions {\n cors?: string\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n for await (const chunk of req) chunks.push(chunk as Buffer)\n const raw = Buffer.concat(chunks).toString('utf8')\n return raw ? JSON.parse(raw) : {}\n}\n\n/**\n * Raw Node `http`/`https` request handler.\n *\n * @example\n * import { createServer } from 'node:http'\n * import { createNodeHandler } from 'sanity-plugin-seofields/server'\n * createServer(createNodeHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY })).listen(3000)\n */\nexport function createNodeHandler(\n config: AiConfig,\n options: NodeAdapterOptions = {},\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiNodeHandler(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n res.setHeader('Content-Type', 'application/json')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'POST') {\n res.writeHead(405)\n res.end(JSON.stringify({error: 'Method not allowed'}))\n return\n }\n\n try {\n const body = (await readJsonBody(req)) as SeoAiRequestBody\n const result = await handle(body)\n res.writeHead(200)\n res.end(JSON.stringify(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.writeHead(500)\n res.end(JSON.stringify({error: message}))\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { A as AiConfig, a as AiIndustry } from './plugin-DoGeZP79.cjs';
|
|
2
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
+
import 'sanity';
|
|
4
|
+
import 'react';
|
|
5
|
+
import './types-DxlPXihz.cjs';
|
|
6
|
+
|
|
7
|
+
interface MinimalRequest {
|
|
8
|
+
method?: string;
|
|
9
|
+
body?: unknown;
|
|
10
|
+
}
|
|
11
|
+
interface MinimalResponse {
|
|
12
|
+
status(code: number): MinimalResponse;
|
|
13
|
+
json(body: unknown): void;
|
|
14
|
+
setHeader(name: string, value: string): void;
|
|
15
|
+
end(): void;
|
|
16
|
+
}
|
|
17
|
+
interface ExpressAdapterOptions {
|
|
18
|
+
cors?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Express (or Express-compatible) request handler. Requires a JSON body parser
|
|
22
|
+
* (e.g. `app.use(express.json())`) mounted before this route.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* import { createExpressHandler } from 'sanity-plugin-seofields/server'
|
|
26
|
+
* app.post('/api/seo-ai', createExpressHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY }))
|
|
27
|
+
*/
|
|
28
|
+
declare function createExpressHandler(config: AiConfig, options?: ExpressAdapterOptions): (req: MinimalRequest, res: MinimalResponse) => Promise<void>;
|
|
29
|
+
|
|
30
|
+
interface FetchAdapterOptions {
|
|
31
|
+
/** Origin allowed to call this endpoint. Only needed when the proxy is deployed on a
|
|
32
|
+
* different origin than the Studio (same-app routes don't hit CORS at all). */
|
|
33
|
+
cors?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Standard `Request -> Response` handler. Works as-is for Next.js App Router route handlers,
|
|
37
|
+
* Cloudflare Workers, Deno, Bun, Remix, and SvelteKit — anything built on the Fetch API.
|
|
38
|
+
*/
|
|
39
|
+
declare function createFetchHandler(config: AiConfig, options?: FetchAdapterOptions): (request: Request) => Promise<Response>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Next.js App Router route handler.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // app/api/seo-ai/route.ts
|
|
46
|
+
* import { createNextRouteHandler } from 'sanity-plugin-seofields/server'
|
|
47
|
+
*
|
|
48
|
+
* export const { POST, OPTIONS } = createNextRouteHandler({
|
|
49
|
+
* provider: 'openai',
|
|
50
|
+
* apiKey: process.env.OPENAI_API_KEY,
|
|
51
|
+
* })
|
|
52
|
+
*/
|
|
53
|
+
declare function createNextRouteHandler(config: AiConfig, options?: FetchAdapterOptions): {
|
|
54
|
+
POST: (request: Request) => Promise<Response>;
|
|
55
|
+
OPTIONS: (request: Request) => Promise<Response>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
interface NodeAdapterOptions {
|
|
59
|
+
cors?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Raw Node `http`/`https` request handler.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* import { createServer } from 'node:http'
|
|
66
|
+
* import { createNodeHandler } from 'sanity-plugin-seofields/server'
|
|
67
|
+
* createServer(createNodeHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY })).listen(3000)
|
|
68
|
+
*/
|
|
69
|
+
declare function createNodeHandler(config: AiConfig, options?: NodeAdapterOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
70
|
+
|
|
71
|
+
type SeoGenField = 'title' | 'description' | 'focusKeyword' | 'keywords' | 'ogTitle' | 'ogDescription' | 'twitterTitle' | 'twitterDescription';
|
|
72
|
+
type MetaContext = {
|
|
73
|
+
title?: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
slug?: string;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
interface SeoAiRequestBody {
|
|
79
|
+
field: SeoGenField;
|
|
80
|
+
content: string;
|
|
81
|
+
focusKeyword?: string;
|
|
82
|
+
keywords?: string[];
|
|
83
|
+
meta?: MetaContext;
|
|
84
|
+
/** Industry chosen in the Studio's `ai.industry` config — forwarded so proxy mode matches direct-provider mode. */
|
|
85
|
+
industry?: AiIndustry;
|
|
86
|
+
/** License key forwarded from the Studio's `ai._licenseKey` — determines which prompt pool proxy mode uses. */
|
|
87
|
+
licenseKey?: string;
|
|
88
|
+
}
|
|
89
|
+
interface SeoAiHandler {
|
|
90
|
+
(body: SeoAiRequestBody): Promise<{
|
|
91
|
+
result: string;
|
|
92
|
+
}>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Runs the full SEO text generation pipeline (prompting, retries, validation) server-side using
|
|
96
|
+
* a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with
|
|
97
|
+
* `endpoint` in the Studio's `ai` config, and one of the framework adapters in
|
|
98
|
+
* `sanity-plugin-seofields/server` to expose it over HTTP.
|
|
99
|
+
*/
|
|
100
|
+
declare function createSeoAiHandler(config: AiConfig): SeoAiHandler;
|
|
101
|
+
|
|
102
|
+
export { type ExpressAdapterOptions, type FetchAdapterOptions, type MinimalRequest, type MinimalResponse, type NodeAdapterOptions, type SeoAiHandler, type SeoAiRequestBody, createExpressHandler, createFetchHandler, createNextRouteHandler, createNodeHandler, createSeoAiHandler };
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { A as AiConfig, a as AiIndustry } from './plugin-DQdThyxG.js';
|
|
2
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
3
|
+
import 'sanity';
|
|
4
|
+
import 'react';
|
|
5
|
+
import './types-DxlPXihz.js';
|
|
6
|
+
|
|
7
|
+
interface MinimalRequest {
|
|
8
|
+
method?: string;
|
|
9
|
+
body?: unknown;
|
|
10
|
+
}
|
|
11
|
+
interface MinimalResponse {
|
|
12
|
+
status(code: number): MinimalResponse;
|
|
13
|
+
json(body: unknown): void;
|
|
14
|
+
setHeader(name: string, value: string): void;
|
|
15
|
+
end(): void;
|
|
16
|
+
}
|
|
17
|
+
interface ExpressAdapterOptions {
|
|
18
|
+
cors?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Express (or Express-compatible) request handler. Requires a JSON body parser
|
|
22
|
+
* (e.g. `app.use(express.json())`) mounted before this route.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* import { createExpressHandler } from 'sanity-plugin-seofields/server'
|
|
26
|
+
* app.post('/api/seo-ai', createExpressHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY }))
|
|
27
|
+
*/
|
|
28
|
+
declare function createExpressHandler(config: AiConfig, options?: ExpressAdapterOptions): (req: MinimalRequest, res: MinimalResponse) => Promise<void>;
|
|
29
|
+
|
|
30
|
+
interface FetchAdapterOptions {
|
|
31
|
+
/** Origin allowed to call this endpoint. Only needed when the proxy is deployed on a
|
|
32
|
+
* different origin than the Studio (same-app routes don't hit CORS at all). */
|
|
33
|
+
cors?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Standard `Request -> Response` handler. Works as-is for Next.js App Router route handlers,
|
|
37
|
+
* Cloudflare Workers, Deno, Bun, Remix, and SvelteKit — anything built on the Fetch API.
|
|
38
|
+
*/
|
|
39
|
+
declare function createFetchHandler(config: AiConfig, options?: FetchAdapterOptions): (request: Request) => Promise<Response>;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Next.js App Router route handler.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* // app/api/seo-ai/route.ts
|
|
46
|
+
* import { createNextRouteHandler } from 'sanity-plugin-seofields/server'
|
|
47
|
+
*
|
|
48
|
+
* export const { POST, OPTIONS } = createNextRouteHandler({
|
|
49
|
+
* provider: 'openai',
|
|
50
|
+
* apiKey: process.env.OPENAI_API_KEY,
|
|
51
|
+
* })
|
|
52
|
+
*/
|
|
53
|
+
declare function createNextRouteHandler(config: AiConfig, options?: FetchAdapterOptions): {
|
|
54
|
+
POST: (request: Request) => Promise<Response>;
|
|
55
|
+
OPTIONS: (request: Request) => Promise<Response>;
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
interface NodeAdapterOptions {
|
|
59
|
+
cors?: string;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Raw Node `http`/`https` request handler.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* import { createServer } from 'node:http'
|
|
66
|
+
* import { createNodeHandler } from 'sanity-plugin-seofields/server'
|
|
67
|
+
* createServer(createNodeHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY })).listen(3000)
|
|
68
|
+
*/
|
|
69
|
+
declare function createNodeHandler(config: AiConfig, options?: NodeAdapterOptions): (req: IncomingMessage, res: ServerResponse) => Promise<void>;
|
|
70
|
+
|
|
71
|
+
type SeoGenField = 'title' | 'description' | 'focusKeyword' | 'keywords' | 'ogTitle' | 'ogDescription' | 'twitterTitle' | 'twitterDescription';
|
|
72
|
+
type MetaContext = {
|
|
73
|
+
title?: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
slug?: string;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
interface SeoAiRequestBody {
|
|
79
|
+
field: SeoGenField;
|
|
80
|
+
content: string;
|
|
81
|
+
focusKeyword?: string;
|
|
82
|
+
keywords?: string[];
|
|
83
|
+
meta?: MetaContext;
|
|
84
|
+
/** Industry chosen in the Studio's `ai.industry` config — forwarded so proxy mode matches direct-provider mode. */
|
|
85
|
+
industry?: AiIndustry;
|
|
86
|
+
/** License key forwarded from the Studio's `ai._licenseKey` — determines which prompt pool proxy mode uses. */
|
|
87
|
+
licenseKey?: string;
|
|
88
|
+
}
|
|
89
|
+
interface SeoAiHandler {
|
|
90
|
+
(body: SeoAiRequestBody): Promise<{
|
|
91
|
+
result: string;
|
|
92
|
+
}>;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Runs the full SEO text generation pipeline (prompting, retries, validation) server-side using
|
|
96
|
+
* a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with
|
|
97
|
+
* `endpoint` in the Studio's `ai` config, and one of the framework adapters in
|
|
98
|
+
* `sanity-plugin-seofields/server` to expose it over HTTP.
|
|
99
|
+
*/
|
|
100
|
+
declare function createSeoAiHandler(config: AiConfig): SeoAiHandler;
|
|
101
|
+
|
|
102
|
+
export { type ExpressAdapterOptions, type FetchAdapterOptions, type MinimalRequest, type MinimalResponse, type NodeAdapterOptions, type SeoAiHandler, type SeoAiRequestBody, createExpressHandler, createFetchHandler, createNextRouteHandler, createNodeHandler, createSeoAiHandler };
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import {
|
|
2
|
+
generateSeoText
|
|
3
|
+
} from "./chunk-Z5AOUU4H.js";
|
|
4
|
+
import {
|
|
5
|
+
__forAwait,
|
|
6
|
+
__spreadProps,
|
|
7
|
+
__spreadValues
|
|
8
|
+
} from "./chunk-7N4MLTMR.js";
|
|
9
|
+
|
|
10
|
+
// src/server/aiHandler.ts
|
|
11
|
+
function isValidBody(body) {
|
|
12
|
+
if (!body || typeof body !== "object") return false;
|
|
13
|
+
const { field, content } = body;
|
|
14
|
+
return typeof field === "string" && typeof content === "string";
|
|
15
|
+
}
|
|
16
|
+
function createSeoAiHandler(config) {
|
|
17
|
+
return async function handleSeoAiRequest(body) {
|
|
18
|
+
if (!isValidBody(body)) {
|
|
19
|
+
throw new Error('Invalid request body: "field" and "content" are required.');
|
|
20
|
+
}
|
|
21
|
+
const { field, content, focusKeyword = "", keywords = [], meta, industry, licenseKey } = body;
|
|
22
|
+
const mergedConfig = __spreadProps(__spreadValues({}, config), {
|
|
23
|
+
industry: industry != null ? industry : config.industry,
|
|
24
|
+
_licenseKey: licenseKey != null ? licenseKey : config._licenseKey
|
|
25
|
+
});
|
|
26
|
+
const result = await generateSeoText(field, content, focusKeyword, keywords, {
|
|
27
|
+
config: mergedConfig,
|
|
28
|
+
meta
|
|
29
|
+
});
|
|
30
|
+
return { result };
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/server/adapters/express.ts
|
|
35
|
+
function createExpressHandler(config, options = {}) {
|
|
36
|
+
const handle = createSeoAiHandler(config);
|
|
37
|
+
return async function seoAiExpressHandler(req, res) {
|
|
38
|
+
if (options.cors) res.setHeader("Access-Control-Allow-Origin", options.cors);
|
|
39
|
+
if (req.method === "OPTIONS") {
|
|
40
|
+
res.status(204).end();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (req.method !== "POST") {
|
|
44
|
+
res.status(405).json({ error: "Method not allowed" });
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const result = await handle(req.body);
|
|
49
|
+
res.status(200).json(result);
|
|
50
|
+
} catch (err) {
|
|
51
|
+
const message = err instanceof Error ? err.message : "AI generation failed.";
|
|
52
|
+
res.status(500).json({ error: message });
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// src/server/adapters/fetch.ts
|
|
58
|
+
function corsHeaders(options) {
|
|
59
|
+
return options.cors ? { "Access-Control-Allow-Origin": options.cors } : {};
|
|
60
|
+
}
|
|
61
|
+
function createFetchHandler(config, options = {}) {
|
|
62
|
+
const handle = createSeoAiHandler(config);
|
|
63
|
+
const headers = __spreadValues({ "Content-Type": "application/json" }, corsHeaders(options));
|
|
64
|
+
return async function seoAiFetchHandler(request) {
|
|
65
|
+
if (request.method === "OPTIONS") {
|
|
66
|
+
return new Response(null, {
|
|
67
|
+
status: 204,
|
|
68
|
+
headers: __spreadProps(__spreadValues({}, headers), {
|
|
69
|
+
"Access-Control-Allow-Methods": "POST, OPTIONS",
|
|
70
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
71
|
+
})
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (request.method !== "POST") {
|
|
75
|
+
return new Response(JSON.stringify({ error: "Method not allowed" }), { status: 405, headers });
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const body = await request.json();
|
|
79
|
+
const result = await handle(body);
|
|
80
|
+
return new Response(JSON.stringify(result), { status: 200, headers });
|
|
81
|
+
} catch (err) {
|
|
82
|
+
const message = err instanceof Error ? err.message : "AI generation failed.";
|
|
83
|
+
return new Response(JSON.stringify({ error: message }), { status: 500, headers });
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// src/server/adapters/nextjs.ts
|
|
89
|
+
function createNextRouteHandler(config, options) {
|
|
90
|
+
const handler = createFetchHandler(config, options);
|
|
91
|
+
return { POST: handler, OPTIONS: handler };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
// src/server/adapters/node.ts
|
|
95
|
+
async function readJsonBody(req) {
|
|
96
|
+
const chunks = [];
|
|
97
|
+
try {
|
|
98
|
+
for (var iter = __forAwait(req), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
99
|
+
const chunk = temp.value;
|
|
100
|
+
chunks.push(chunk);
|
|
101
|
+
}
|
|
102
|
+
} catch (temp) {
|
|
103
|
+
error = [temp];
|
|
104
|
+
} finally {
|
|
105
|
+
try {
|
|
106
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
107
|
+
} finally {
|
|
108
|
+
if (error)
|
|
109
|
+
throw error[0];
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const raw = Buffer.concat(chunks).toString("utf8");
|
|
113
|
+
return raw ? JSON.parse(raw) : {};
|
|
114
|
+
}
|
|
115
|
+
function createNodeHandler(config, options = {}) {
|
|
116
|
+
const handle = createSeoAiHandler(config);
|
|
117
|
+
return async function seoAiNodeHandler(req, res) {
|
|
118
|
+
if (options.cors) res.setHeader("Access-Control-Allow-Origin", options.cors);
|
|
119
|
+
res.setHeader("Content-Type", "application/json");
|
|
120
|
+
if (req.method === "OPTIONS") {
|
|
121
|
+
res.writeHead(204);
|
|
122
|
+
res.end();
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
if (req.method !== "POST") {
|
|
126
|
+
res.writeHead(405);
|
|
127
|
+
res.end(JSON.stringify({ error: "Method not allowed" }));
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
try {
|
|
131
|
+
const body = await readJsonBody(req);
|
|
132
|
+
const result = await handle(body);
|
|
133
|
+
res.writeHead(200);
|
|
134
|
+
res.end(JSON.stringify(result));
|
|
135
|
+
} catch (err) {
|
|
136
|
+
const message = err instanceof Error ? err.message : "AI generation failed.";
|
|
137
|
+
res.writeHead(500);
|
|
138
|
+
res.end(JSON.stringify({ error: message }));
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
export {
|
|
143
|
+
createExpressHandler,
|
|
144
|
+
createFetchHandler,
|
|
145
|
+
createNextRouteHandler,
|
|
146
|
+
createNodeHandler,
|
|
147
|
+
createSeoAiHandler
|
|
148
|
+
};
|
|
149
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/server/aiHandler.ts","../src/server/adapters/express.ts","../src/server/adapters/fetch.ts","../src/server/adapters/nextjs.ts","../src/server/adapters/node.ts"],"sourcesContent":["import type {AiConfig, AiIndustry} from '../plugin'\nimport {generateSeoText} from '../utils/seoContentGen'\nimport type {MetaContext, SeoGenField} from '../utils/seoPrompts'\n\nexport interface SeoAiRequestBody {\n field: SeoGenField\n content: string\n focusKeyword?: string\n keywords?: string[]\n meta?: MetaContext\n /** Industry chosen in the Studio's `ai.industry` config — forwarded so proxy mode matches direct-provider mode. */\n industry?: AiIndustry\n /** License key forwarded from the Studio's `ai._licenseKey` — determines which prompt pool proxy mode uses. */\n licenseKey?: string\n}\n\nexport interface SeoAiHandler {\n (body: SeoAiRequestBody): Promise<{result: string}>\n}\n\nfunction isValidBody(body: unknown): body is SeoAiRequestBody {\n if (!body || typeof body !== 'object') return false\n const {field, content} = body as Record<string, unknown>\n return typeof field === 'string' && typeof content === 'string'\n}\n\n/**\n * Runs the full SEO text generation pipeline (prompting, retries, validation) server-side using\n * a real `AiConfig` — including `apiKey` — which never has to be sent to the browser. Pair with\n * `endpoint` in the Studio's `ai` config, and one of the framework adapters in\n * `sanity-plugin-seofields/server` to expose it over HTTP.\n */\nexport function createSeoAiHandler(config: AiConfig): SeoAiHandler {\n return async function handleSeoAiRequest(body: SeoAiRequestBody): Promise<{result: string}> {\n if (!isValidBody(body)) {\n throw new Error('Invalid request body: \"field\" and \"content\" are required.')\n }\n\n const {field, content, focusKeyword = '', keywords = [], meta, industry, licenseKey} = body\n const mergedConfig: AiConfig = {\n ...config,\n industry: industry ?? config.industry,\n _licenseKey: licenseKey ?? config._licenseKey,\n }\n const result = await generateSeoText(field, content, focusKeyword, keywords, {\n config: mergedConfig,\n meta,\n })\n return {result}\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\n// Duck-typed instead of importing `express` types, so the package has no dependency on Express.\nexport interface MinimalRequest {\n method?: string\n body?: unknown\n}\n\nexport interface MinimalResponse {\n status(code: number): MinimalResponse\n json(body: unknown): void\n setHeader(name: string, value: string): void\n end(): void\n}\n\nexport interface ExpressAdapterOptions {\n cors?: string\n}\n\n/**\n * Express (or Express-compatible) request handler. Requires a JSON body parser\n * (e.g. `app.use(express.json())`) mounted before this route.\n *\n * @example\n * import { createExpressHandler } from 'sanity-plugin-seofields/server'\n * app.post('/api/seo-ai', createExpressHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY }))\n */\nexport function createExpressHandler(\n config: AiConfig,\n options: ExpressAdapterOptions = {},\n): (req: MinimalRequest, res: MinimalResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiExpressHandler(\n req: MinimalRequest,\n res: MinimalResponse,\n ): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n\n if (req.method === 'OPTIONS') {\n res.status(204).end()\n return\n }\n\n if (req.method !== 'POST') {\n res.status(405).json({error: 'Method not allowed'})\n return\n }\n\n try {\n const result = await handle(req.body as SeoAiRequestBody)\n res.status(200).json(result)\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.status(500).json({error: message})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface FetchAdapterOptions {\n /** Origin allowed to call this endpoint. Only needed when the proxy is deployed on a\n * different origin than the Studio (same-app routes don't hit CORS at all). */\n cors?: string\n}\n\nfunction corsHeaders(options: FetchAdapterOptions): Record<string, string> {\n return options.cors ? {'Access-Control-Allow-Origin': options.cors} : {}\n}\n\n/**\n * Standard `Request -> Response` handler. Works as-is for Next.js App Router route handlers,\n * Cloudflare Workers, Deno, Bun, Remix, and SvelteKit — anything built on the Fetch API.\n */\nexport function createFetchHandler(\n config: AiConfig,\n options: FetchAdapterOptions = {},\n): (request: Request) => Promise<Response> {\n const handle = createSeoAiHandler(config)\n const headers = {'Content-Type': 'application/json', ...corsHeaders(options)}\n\n return async function seoAiFetchHandler(request: Request): Promise<Response> {\n if (request.method === 'OPTIONS') {\n return new Response(null, {\n status: 204,\n headers: {\n ...headers,\n 'Access-Control-Allow-Methods': 'POST, OPTIONS',\n 'Access-Control-Allow-Headers': 'Content-Type',\n },\n })\n }\n\n if (request.method !== 'POST') {\n return new Response(JSON.stringify({error: 'Method not allowed'}), {status: 405, headers})\n }\n\n try {\n const body = (await request.json()) as SeoAiRequestBody\n const result = await handle(body)\n return new Response(JSON.stringify(result), {status: 200, headers})\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n return new Response(JSON.stringify({error: message}), {status: 500, headers})\n }\n }\n}\n","import type {AiConfig} from '../../plugin'\nimport {createFetchHandler, type FetchAdapterOptions} from './fetch'\n\n/**\n * Next.js App Router route handler.\n *\n * @example\n * // app/api/seo-ai/route.ts\n * import { createNextRouteHandler } from 'sanity-plugin-seofields/server'\n *\n * export const { POST, OPTIONS } = createNextRouteHandler({\n * provider: 'openai',\n * apiKey: process.env.OPENAI_API_KEY,\n * })\n */\nexport function createNextRouteHandler(\n config: AiConfig,\n options?: FetchAdapterOptions,\n): {\n POST: (request: Request) => Promise<Response>\n OPTIONS: (request: Request) => Promise<Response>\n} {\n const handler = createFetchHandler(config, options)\n return {POST: handler, OPTIONS: handler}\n}\n","import type {IncomingMessage, ServerResponse} from 'node:http'\n\nimport type {AiConfig} from '../../plugin'\nimport {createSeoAiHandler, type SeoAiRequestBody} from '../aiHandler'\n\nexport interface NodeAdapterOptions {\n cors?: string\n}\n\nasync function readJsonBody(req: IncomingMessage): Promise<unknown> {\n const chunks: Buffer[] = []\n for await (const chunk of req) chunks.push(chunk as Buffer)\n const raw = Buffer.concat(chunks).toString('utf8')\n return raw ? JSON.parse(raw) : {}\n}\n\n/**\n * Raw Node `http`/`https` request handler.\n *\n * @example\n * import { createServer } from 'node:http'\n * import { createNodeHandler } from 'sanity-plugin-seofields/server'\n * createServer(createNodeHandler({ provider: 'openai', apiKey: process.env.OPENAI_API_KEY })).listen(3000)\n */\nexport function createNodeHandler(\n config: AiConfig,\n options: NodeAdapterOptions = {},\n): (req: IncomingMessage, res: ServerResponse) => Promise<void> {\n const handle = createSeoAiHandler(config)\n\n return async function seoAiNodeHandler(req: IncomingMessage, res: ServerResponse): Promise<void> {\n if (options.cors) res.setHeader('Access-Control-Allow-Origin', options.cors)\n res.setHeader('Content-Type', 'application/json')\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204)\n res.end()\n return\n }\n\n if (req.method !== 'POST') {\n res.writeHead(405)\n res.end(JSON.stringify({error: 'Method not allowed'}))\n return\n }\n\n try {\n const body = (await readJsonBody(req)) as SeoAiRequestBody\n const result = await handle(body)\n res.writeHead(200)\n res.end(JSON.stringify(result))\n } catch (err) {\n const message = err instanceof Error ? err.message : 'AI generation failed.'\n res.writeHead(500)\n res.end(JSON.stringify({error: message}))\n }\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as SchemaOrgCreativeWorkData } from './types-DRLUGLtX.js';
|
|
2
2
|
|
|
3
3
|
/** Shared content item nested within the SocialMediaPosting schema */
|
|
4
4
|
interface SocialMediaPostingSharedContent {
|
|
@@ -21,4 +21,4 @@ interface SchemaOrgSocialMediaPostingConfig {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export type {
|
|
24
|
+
export type { SchemaOrgSocialMediaPostingData as S, SchemaOrgSocialMediaPostingConfig as a };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { d as SchemaOrgCreativeWorkData } from './types-DP-DiW6f.cjs';
|
|
2
2
|
|
|
3
3
|
/** Shared content item nested within the SocialMediaPosting schema */
|
|
4
4
|
interface SocialMediaPostingSharedContent {
|
|
@@ -21,4 +21,4 @@ interface SchemaOrgSocialMediaPostingConfig {
|
|
|
21
21
|
};
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
export type {
|
|
24
|
+
export type { SchemaOrgSocialMediaPostingData as S, SchemaOrgSocialMediaPostingConfig as a };
|
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { JSX } from 'react';
|
|
2
|
+
import { a as SanityImage } from './types-DxlPXihz.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* <SchemaOrgScripts> — Renders multiple Schema.org JSON-LD script tags
|
|
6
|
+
* from a combined `schemaOrg` array field.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* import { SchemaOrgScripts } from 'sanity-plugin-seofields/next'
|
|
11
|
+
*
|
|
12
|
+
* const data = await sanityFetch({ query: `*[_type == "settings"][0]{ structuredData }` })
|
|
13
|
+
*
|
|
14
|
+
* <SchemaOrgScripts data={data.structuredData} />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
declare function buildSchemaOrgJsonLd(item: Record<string, unknown>): Record<string, unknown> | null;
|
|
19
|
+
declare function buildSchemaOrgJsonLds(data?: Array<Record<string, unknown>> | null): Array<Record<string, unknown>>;
|
|
20
|
+
interface SchemaOrgScriptsProps {
|
|
21
|
+
/** Array of Schema.org items from the combined `schemaOrg` field. */
|
|
22
|
+
data?: Array<Record<string, unknown>> | null;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Renders one `<script type="application/ld+json">` tag per Schema.org item.
|
|
26
|
+
* Skips items that fail validation (missing required fields).
|
|
27
|
+
*/
|
|
28
|
+
declare function SchemaOrgScripts({ data }: SchemaOrgScriptsProps): JSX.Element | null;
|
|
2
29
|
|
|
3
30
|
/** Copyright year: static number or dynamic (current year) */
|
|
4
31
|
type SchemaOrgCopyrightYear = number | {
|
|
@@ -1230,4 +1257,4 @@ interface SchemaOrgWebsiteConfig {
|
|
|
1230
1257
|
};
|
|
1231
1258
|
}
|
|
1232
1259
|
|
|
1233
|
-
export type
|
|
1260
|
+
export { type SchemaOrgFAQPageConfig as $, type SchemaOrgOpinionNewsArticleData as A, type SchemaOrgOrganizationData as B, type SchemaOrgPersonData as C, type SchemaOrgPlaceData as D, type SchemaOrgPostalAddressData as E, type SchemaOrgProductData as F, type SchemaOrgProfilePageData as G, type SchemaOrgRecipeData as H, type SchemaOrgRestaurantData as I, type SchemaOrgReviewData as J, type SchemaOrgServiceData as K, type SchemaOrgSoftwareApplicationData as L, type SchemaOrgVideoObjectData as M, type SchemaOrgWebApplicationData as N, type SchemaOrgWebPageData as O, type SchemaOrgWebsiteData as P, type SchemaOrgAggregateRatingConfig as Q, type SchemaOrgArticleConfig as R, SchemaOrgScripts as S, type SchemaOrgBlogPostingConfig as T, type SchemaOrgBookConfig as U, type SchemaOrgBrandConfig as V, type SchemaOrgBreadcrumbListConfig as W, type SchemaOrgContactPointConfig as X, type SchemaOrgCountryConfig as Y, type SchemaOrgCourseConfig as Z, type SchemaOrgEventConfig as _, type SchemaOrgScriptsProps as a, type SchemaOrgHowToConfig as a0, type SchemaOrgImageObjectConfig as a1, type SchemaOrgItemListConfig as a2, type SchemaOrgJobPostingConfig as a3, type SchemaOrgLegalServiceConfig as a4, type SchemaOrgLocalBusinessConfig as a5, type SchemaOrgMovieConfig as a6, type SchemaOrgMusicAlbumConfig as a7, type SchemaOrgMusicRecordingConfig as a8, type SchemaOrgNewsArticleConfig as a9, type SchemaOrgThingData as aA, type SchemaOrgOfferConfig as aa, type SchemaOrgOpinionNewsArticleConfig as ab, type SchemaOrgOrganizationConfig as ac, type SchemaOrgPersonConfig as ad, type SchemaOrgPlaceConfig as ae, type SchemaOrgPostalAddressConfig as af, type SchemaOrgProductConfig as ag, type SchemaOrgProfilePageConfig as ah, type SchemaOrgRecipeConfig as ai, type SchemaOrgRestaurantConfig as aj, type SchemaOrgReviewConfig as ak, type SchemaOrgServiceConfig as al, type SchemaOrgSoftwareApplicationConfig as am, type SchemaOrgVideoObjectConfig as an, type SchemaOrgWebApplicationConfig as ao, type SchemaOrgWebPageConfig as ap, type SchemaOrgWebsiteConfig as aq, type OrganizationContactPoint as ar, type SchemaOrgAggregateRating as as, type SchemaOrgArchivedAt as at, type SchemaOrgContentRating as au, type SchemaOrgCopyrightYear as av, type SchemaOrgImageInput as aw, type SchemaOrgOrganizationInput as ax, type SchemaOrgPersonOrOrganization as ay, type SchemaOrgTextOrUrl as az, buildSchemaOrgJsonLd as b, buildSchemaOrgJsonLds as c, type SchemaOrgCreativeWorkData as d, type SchemaOrgAggregateRatingData as e, type SchemaOrgArticleData as f, type SchemaOrgBlogPostingData as g, type SchemaOrgBookData as h, type SchemaOrgBrandData as i, type SchemaOrgBreadcrumbListData as j, type SchemaOrgContactPointData as k, type SchemaOrgCountryData as l, type SchemaOrgCourseData as m, type SchemaOrgEventData as n, type SchemaOrgFAQPageData as o, type SchemaOrgHowToData as p, type SchemaOrgImageObjectData as q, type SchemaOrgItemListData as r, type SchemaOrgJobPostingData as s, type SchemaOrgLegalServiceData as t, type SchemaOrgLocalBusinessData as u, type SchemaOrgMovieData as v, type SchemaOrgMusicAlbumData as w, type SchemaOrgMusicRecordingData as x, type SchemaOrgNewsArticleData as y, type SchemaOrgOfferData as z };
|