@smalk/nextjs-ads 0.1.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 +21 -0
- package/README.md +103 -0
- package/dist/app.cjs +191 -0
- package/dist/app.cjs.map +1 -0
- package/dist/app.d.cts +15 -0
- package/dist/app.d.ts +15 -0
- package/dist/app.js +54 -0
- package/dist/app.js.map +1 -0
- package/dist/chunk-HX4ZGDYQ.js +31 -0
- package/dist/chunk-HX4ZGDYQ.js.map +1 -0
- package/dist/chunk-YA6M2IA4.js +92 -0
- package/dist/chunk-YA6M2IA4.js.map +1 -0
- package/dist/index.cjs +58 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +26 -0
- package/dist/index.d.ts +26 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/middleware.cjs +185 -0
- package/dist/middleware.cjs.map +1 -0
- package/dist/middleware.d.cts +8 -0
- package/dist/middleware.d.ts +8 -0
- package/dist/middleware.js +48 -0
- package/dist/middleware.js.map +1 -0
- package/dist/pages.cjs +196 -0
- package/dist/pages.cjs.map +1 -0
- package/dist/pages.d.cts +21 -0
- package/dist/pages.d.ts +21 -0
- package/dist/pages.js +58 -0
- package/dist/pages.js.map +1 -0
- package/package.json +75 -0
package/dist/pages.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {
|
|
2
|
+
fetchAd
|
|
3
|
+
} from "./chunk-YA6M2IA4.js";
|
|
4
|
+
import "./chunk-HX4ZGDYQ.js";
|
|
5
|
+
|
|
6
|
+
// src/pages.ts
|
|
7
|
+
import * as React from "react";
|
|
8
|
+
async function getSmalkAd(req, opts = {}) {
|
|
9
|
+
const headers = req.headers ?? {};
|
|
10
|
+
const url = req.url ?? "/";
|
|
11
|
+
const host = headerValue(headers, "host") ?? "";
|
|
12
|
+
const pageUrl = host ? `https://${host}${url}` : url;
|
|
13
|
+
const userAgent = headerValue(headers, "user-agent") ?? "";
|
|
14
|
+
const referer = headerValue(headers, "referer") ?? "";
|
|
15
|
+
const clientIp = pickClientIp(headers);
|
|
16
|
+
let preview = opts.preview;
|
|
17
|
+
if (preview === void 0) {
|
|
18
|
+
const m = url.match(/[?&]preview=([^&]+)/);
|
|
19
|
+
if (m) {
|
|
20
|
+
const v = decodeURIComponent(m[1]);
|
|
21
|
+
preview = v === "1" || v === "true" ? true : v;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return fetchAd(
|
|
25
|
+
{ pageUrl, userAgent, referer, clientIp },
|
|
26
|
+
{ revalidate: opts.revalidate, preview }
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
function AdHtml({ ad, className }) {
|
|
30
|
+
if (!ad) {
|
|
31
|
+
return React.createElement("span", {
|
|
32
|
+
"data-smalk": "comment",
|
|
33
|
+
dangerouslySetInnerHTML: { __html: "<!-- smalk: no ad -->" }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
return React.createElement("div", {
|
|
37
|
+
className: className ?? "smalk-ads",
|
|
38
|
+
"data-smalk-booking": ad.bookingId ?? void 0,
|
|
39
|
+
dangerouslySetInnerHTML: { __html: ad.html }
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function headerValue(h, key) {
|
|
43
|
+
const v = h[key] ?? h[key.toLowerCase()];
|
|
44
|
+
if (Array.isArray(v)) return v[0] ?? null;
|
|
45
|
+
return v ?? null;
|
|
46
|
+
}
|
|
47
|
+
function pickClientIp(h) {
|
|
48
|
+
for (const key of ["cf-connecting-ip", "x-real-ip", "x-forwarded-for"]) {
|
|
49
|
+
const v = headerValue(h, key);
|
|
50
|
+
if (v) return v.split(",")[0].trim();
|
|
51
|
+
}
|
|
52
|
+
return "";
|
|
53
|
+
}
|
|
54
|
+
export {
|
|
55
|
+
AdHtml,
|
|
56
|
+
getSmalkAd
|
|
57
|
+
};
|
|
58
|
+
//# sourceMappingURL=pages.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/pages.ts"],"sourcesContent":["import * as React from 'react';\nimport type { IncomingMessage } from 'node:http';\nimport { fetchAd } from './client';\nimport type { AdResult } from './index';\n\nexport interface MinimalReq {\n url?: string;\n headers: Record<string, string | string[] | undefined>;\n}\n\nexport interface GetSmalkAdOptions {\n revalidate?: number;\n /** Preview mode: `true` (PARAGRAPH placeholder) or a format string. Bypasses booking lookup. */\n preview?: boolean | string;\n}\n\nexport async function getSmalkAd(\n req: IncomingMessage | MinimalReq,\n opts: GetSmalkAdOptions = {},\n): Promise<AdResult | null> {\n const headers = (req as MinimalReq).headers ?? {};\n const url = (req as MinimalReq).url ?? '/';\n const host = headerValue(headers, 'host') ?? '';\n const pageUrl = host ? `https://${host}${url}` : url;\n const userAgent = headerValue(headers, 'user-agent') ?? '';\n const referer = headerValue(headers, 'referer') ?? '';\n const clientIp = pickClientIp(headers);\n\n // Auto-forward `?preview=` from the page URL (so visiting /blog/x?preview=1 works without\n // a callsite change). Explicit opts.preview takes precedence.\n let preview = opts.preview;\n if (preview === undefined) {\n const m = url.match(/[?&]preview=([^&]+)/);\n if (m) {\n const v = decodeURIComponent(m[1]);\n preview = v === '1' || v === 'true' ? true : v;\n }\n }\n\n return fetchAd(\n { pageUrl, userAgent, referer, clientIp },\n { revalidate: opts.revalidate, preview },\n );\n}\n\nexport interface AdHtmlProps {\n ad: AdResult | null;\n className?: string;\n}\n\nexport function AdHtml({ ad, className }: AdHtmlProps): React.ReactElement {\n if (!ad) {\n return React.createElement('span', {\n 'data-smalk': 'comment',\n dangerouslySetInnerHTML: { __html: '<!-- smalk: no ad -->' },\n });\n }\n return React.createElement('div', {\n className: className ?? 'smalk-ads',\n 'data-smalk-booking': ad.bookingId ?? undefined,\n dangerouslySetInnerHTML: { __html: ad.html },\n });\n}\n\nfunction headerValue(h: Record<string, string | string[] | undefined>, key: string): string | null {\n const v = h[key] ?? h[key.toLowerCase()];\n if (Array.isArray(v)) return v[0] ?? null;\n return v ?? null;\n}\n\nfunction pickClientIp(h: Record<string, string | string[] | undefined>): string {\n for (const key of ['cf-connecting-ip', 'x-real-ip', 'x-forwarded-for']) {\n const v = headerValue(h, key);\n if (v) return v.split(',')[0].trim();\n }\n return '';\n}\n"],"mappings":";;;;;;AAAA,YAAY,WAAW;AAgBvB,eAAsB,WACpB,KACA,OAA0B,CAAC,GACD;AAC1B,QAAM,UAAW,IAAmB,WAAW,CAAC;AAChD,QAAM,MAAO,IAAmB,OAAO;AACvC,QAAM,OAAO,YAAY,SAAS,MAAM,KAAK;AAC7C,QAAM,UAAU,OAAO,WAAW,IAAI,GAAG,GAAG,KAAK;AACjD,QAAM,YAAY,YAAY,SAAS,YAAY,KAAK;AACxD,QAAM,UAAU,YAAY,SAAS,SAAS,KAAK;AACnD,QAAM,WAAW,aAAa,OAAO;AAIrC,MAAI,UAAU,KAAK;AACnB,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,IAAI,MAAM,qBAAqB;AACzC,QAAI,GAAG;AACL,YAAM,IAAI,mBAAmB,EAAE,CAAC,CAAC;AACjC,gBAAU,MAAM,OAAO,MAAM,SAAS,OAAO;AAAA,IAC/C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,EAAE,SAAS,WAAW,SAAS,SAAS;AAAA,IACxC,EAAE,YAAY,KAAK,YAAY,QAAQ;AAAA,EACzC;AACF;AAOO,SAAS,OAAO,EAAE,IAAI,UAAU,GAAoC;AACzE,MAAI,CAAC,IAAI;AACP,WAAa,oBAAc,QAAQ;AAAA,MACjC,cAAc;AAAA,MACd,yBAAyB,EAAE,QAAQ,wBAAwB;AAAA,IAC7D,CAAC;AAAA,EACH;AACA,SAAa,oBAAc,OAAO;AAAA,IAChC,WAAW,aAAa;AAAA,IACxB,sBAAsB,GAAG,aAAa;AAAA,IACtC,yBAAyB,EAAE,QAAQ,GAAG,KAAK;AAAA,EAC7C,CAAC;AACH;AAEA,SAAS,YAAY,GAAkD,KAA4B;AACjG,QAAM,IAAI,EAAE,GAAG,KAAK,EAAE,IAAI,YAAY,CAAC;AACvC,MAAI,MAAM,QAAQ,CAAC,EAAG,QAAO,EAAE,CAAC,KAAK;AACrC,SAAO,KAAK;AACd;AAEA,SAAS,aAAa,GAA0D;AAC9E,aAAW,OAAO,CAAC,oBAAoB,aAAa,iBAAiB,GAAG;AACtE,UAAM,IAAI,YAAY,GAAG,GAAG;AAC5B,QAAI,EAAG,QAAO,EAAE,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK;AAAA,EACrC;AACA,SAAO;AACT;","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@smalk/nextjs-ads",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Smalk AI Ads — server-side ad injection for Next.js (App Router, Pages Router, middleware)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./app": {
|
|
17
|
+
"types": "./dist/app.d.ts",
|
|
18
|
+
"import": "./dist/app.js",
|
|
19
|
+
"require": "./dist/app.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./pages": {
|
|
22
|
+
"types": "./dist/pages.d.ts",
|
|
23
|
+
"import": "./dist/pages.js",
|
|
24
|
+
"require": "./dist/pages.cjs"
|
|
25
|
+
},
|
|
26
|
+
"./middleware": {
|
|
27
|
+
"types": "./dist/middleware.d.ts",
|
|
28
|
+
"import": "./dist/middleware.js",
|
|
29
|
+
"require": "./dist/middleware.cjs"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"README.md",
|
|
35
|
+
"LICENSE"
|
|
36
|
+
],
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsup",
|
|
39
|
+
"test": "vitest run",
|
|
40
|
+
"test:watch": "vitest",
|
|
41
|
+
"test:e2e": "playwright test --config e2e/playwright.config.ts",
|
|
42
|
+
"test:e2e:install": "playwright install chromium",
|
|
43
|
+
"typecheck": "tsc --noEmit",
|
|
44
|
+
"prepublishOnly": "npm run build"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"next": ">=13.4.0",
|
|
48
|
+
"react": ">=18.0.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@playwright/test": "^1.48.0",
|
|
52
|
+
"@testing-library/react": "^16.0.0",
|
|
53
|
+
"@types/node": "^20.0.0",
|
|
54
|
+
"@types/react": "^18.0.0",
|
|
55
|
+
"happy-dom": "^15.0.0",
|
|
56
|
+
"next": "^15.0.0",
|
|
57
|
+
"react": "^18.0.0",
|
|
58
|
+
"react-dom": "^18.0.0",
|
|
59
|
+
"server-only": "^0.0.1",
|
|
60
|
+
"tsup": "^8.0.0",
|
|
61
|
+
"typescript": "^5.4.0",
|
|
62
|
+
"vitest": "^2.0.0"
|
|
63
|
+
},
|
|
64
|
+
"engines": {
|
|
65
|
+
"node": ">=18.0.0"
|
|
66
|
+
},
|
|
67
|
+
"keywords": [
|
|
68
|
+
"smalk",
|
|
69
|
+
"ai-ads",
|
|
70
|
+
"nextjs",
|
|
71
|
+
"ssr",
|
|
72
|
+
"ads",
|
|
73
|
+
"publisher"
|
|
74
|
+
]
|
|
75
|
+
}
|