@ienlab/cloud-functions-library 1.0.0-dev.10 → 1.0.0-dev.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/handlers/ssr-dynamic-og.d.ts +8 -2
- package/dist/index.js +1 -1
- package/dist/index.mjs +42 -18
- package/package.json +1 -1
|
@@ -1,12 +1,18 @@
|
|
|
1
|
-
import { HttpsFunction } from 'firebase-functions/v2/https';
|
|
1
|
+
import { HttpsFunction, Request } from 'firebase-functions/v2/https';
|
|
2
2
|
export interface OGData {
|
|
3
3
|
title: string;
|
|
4
4
|
description: string;
|
|
5
5
|
image: string;
|
|
6
6
|
}
|
|
7
|
+
export interface SSRResolveContext {
|
|
8
|
+
req: Request;
|
|
9
|
+
pathname: string;
|
|
10
|
+
searchParams: URLSearchParams;
|
|
11
|
+
match: RegExpMatchArray;
|
|
12
|
+
}
|
|
7
13
|
export interface SSRResolver {
|
|
8
14
|
pattern: RegExp;
|
|
9
|
-
resolve: (id: string) => Promise<OGData | null>;
|
|
15
|
+
resolve: (id: string, context: SSRResolveContext) => Promise<OGData | null>;
|
|
10
16
|
}
|
|
11
17
|
export interface SSRDynamicOGConfig {
|
|
12
18
|
spaUrl: string;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("firebase-admin/firestore"),t=require("firebase-functions/v2/https");function n(e){return{...e.data(),id:e.id}}function r(e,t,n){let r=e.headers.origin;return r&&n.includes(r)&&(t.set(`Access-Control-Allow-Origin`,r),t.set(`Vary`,`Origin`)),t.set(`Access-Control-Allow-Methods`,`POST, OPTIONS`),t.set(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`?(t.status(204).send(),!1):e.method===`POST`?!0:(t.status(405).send({error:`Method Not Allowed`}),!1)}var i=()=>({updateAt:e.FieldValue.serverTimestamp(),deletedAt:e.FieldValue.serverTimestamp()}),a=()=>({updateAt:e.FieldValue.serverTimestamp(),deletedAt:null});function o(e){let{spaUrl:n,defaultOG:r,resolvers:i,region:a=`asia-northeast3`}=e,o=null;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});let e=require("firebase-admin/firestore"),t=require("firebase-functions/v2/https");function n(e){return{...e.data(),id:e.id}}function r(e,t,n){let r=e.headers.origin;return r&&n.includes(r)&&(t.set(`Access-Control-Allow-Origin`,r),t.set(`Vary`,`Origin`)),t.set(`Access-Control-Allow-Methods`,`POST, OPTIONS`),t.set(`Access-Control-Allow-Headers`,`Content-Type, Authorization`),e.method===`OPTIONS`?(t.status(204).send(),!1):e.method===`POST`?!0:(t.status(405).send({error:`Method Not Allowed`}),!1)}var i=()=>({updateAt:e.FieldValue.serverTimestamp(),deletedAt:e.FieldValue.serverTimestamp()}),a=()=>({updateAt:e.FieldValue.serverTimestamp(),deletedAt:null});function o(e){let{spaUrl:n,defaultOG:r,resolvers:i,region:a=`asia-northeast3`}=e,o=null,s=0;function c(){let e=Date.now();return(!o||e-s>18e5)&&(s=e,o=fetch(n,{signal:AbortSignal.timeout(5e3)}).then(async e=>{if(!e.ok)throw o=null,s=0,Error(`Failed to fetch template: ${e.status}`);return e.text()}).catch(e=>{throw o=null,s=0,e})),o}function l(e){return e?String(e).replace(/&/g,`&`).replace(/</g,`<`).replace(/>/g,`>`).replace(/"/g,`"`).replace(/'/g,`'`):``}function u(e,t,n,r){let i=l(r),a=RegExp(`(<meta\\s+[^>]*${t}=["']${n}["'][^>]*>)`,`gi`),o=!1,s=e.replace(a,e=>(o=!0,/\bcontent=/i.test(e)?e.replace(/\bcontent=(["'])(.*?)\1/i,`content=$1${i}$1`):e.replace(/(\/?>)$/,` content="${i}"$1`)));if(!o){let e=`<meta ${t}="${n}" content="${i}">`;return s.replace(/(<\/head>)/i,`${e}\n$1`)}return s}function d(e,t,n,r){let i=l(t),a=e;return a=/<title>.*<\/title>/i.test(a)?a.replace(/(<title>)[^<]*(<\/title>)/i,`$1${i}$2`):a.replace(/(<\/head>)/i,`<title>${i}</title>\n$1`),a=u(a,`name`,`description`,n),a=u(a,`property`,`og:title`,t),a=u(a,`property`,`og:description`,n),a=u(a,`property`,`og:image`,r),a=u(a,`property`,`og:type`,`website`),a=u(a,`name`,`twitter:card`,`summary_large_image`),a=u(a,`name`,`twitter:title`,t),a=u(a,`name`,`twitter:description`,n),a=u(a,`name`,`twitter:image`,r),a}return(0,t.onRequest)({region:a},async(e,t)=>{let a=Date.now(),o=e.path,s=new URL(e.url,n),l=s.searchParams;try{let n=r;for(let t of i){let r=o.match(t.pattern);if(!r)continue;let i=r[1]??r[0];try{let a=await t.resolve(i,{req:e,pathname:o,searchParams:l,match:r});if(a){n=a;break}}catch(e){console.error(`[SSRDynamicOG] Failed to resolve "${o}${s.search}" with pattern ${t.pattern}:`,e)}}let u=d(await c(),n.title,n.description,n.image);console.log(`[SSRDynamicOG] ${o}${s.search} → ${n.title} (${Date.now()-a}ms)`),t.setHeader(`Content-Type`,`text/html; charset=utf-8`),t.status(200).send(u)}catch(e){console.error(`[SSRDynamicOG] error:`,e),t.redirect(302,n)}})}exports.applyCors=r,exports.createSSRDynamicOG=o,exports.del=i,exports.snapshotToData=n,exports.undel=a;
|
package/dist/index.mjs
CHANGED
|
@@ -25,32 +25,56 @@ var i = () => ({
|
|
|
25
25
|
//#endregion
|
|
26
26
|
//#region src/handlers/ssr-dynamic-og.ts
|
|
27
27
|
function o(e) {
|
|
28
|
-
let { spaUrl: n, defaultOG: r, resolvers: i, region: a = "asia-northeast3" } = e, o = null;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
28
|
+
let { spaUrl: n, defaultOG: r, resolvers: i, region: a = "asia-northeast3" } = e, o = null, s = 0;
|
|
29
|
+
function c() {
|
|
30
|
+
let e = Date.now();
|
|
31
|
+
return (!o || e - s > 18e5) && (s = e, o = fetch(n, { signal: AbortSignal.timeout(5e3) }).then(async (e) => {
|
|
32
|
+
if (!e.ok) throw o = null, s = 0, Error(`Failed to fetch template: ${e.status}`);
|
|
33
|
+
return e.text();
|
|
34
|
+
}).catch((e) => {
|
|
35
|
+
throw o = null, s = 0, e;
|
|
36
|
+
})), o;
|
|
34
37
|
}
|
|
35
|
-
function
|
|
36
|
-
return e
|
|
38
|
+
function l(e) {
|
|
39
|
+
return e ? String(e).replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'") : "";
|
|
40
|
+
}
|
|
41
|
+
function u(e, t, n, r) {
|
|
42
|
+
let i = l(r), a = RegExp(`(<meta\\s+[^>]*${t}=["']${n}["'][^>]*>)`, "gi"), o = !1, s = e.replace(a, (e) => (o = !0, /\bcontent=/i.test(e) ? e.replace(/\bcontent=(["'])(.*?)\1/i, `content=$1${i}$1`) : e.replace(/(\/?>)$/, ` content="${i}"$1`)));
|
|
43
|
+
if (!o) {
|
|
44
|
+
let e = `<meta ${t}="${n}" content="${i}">`;
|
|
45
|
+
return s.replace(/(<\/head>)/i, `${e}\n$1`);
|
|
46
|
+
}
|
|
47
|
+
return s;
|
|
48
|
+
}
|
|
49
|
+
function d(e, t, n, r) {
|
|
50
|
+
let i = l(t), a = e;
|
|
51
|
+
return a = /<title>.*<\/title>/i.test(a) ? a.replace(/(<title>)[^<]*(<\/title>)/i, `$1${i}$2`) : a.replace(/(<\/head>)/i, `<title>${i}</title>\n$1`), a = u(a, "name", "description", n), a = u(a, "property", "og:title", t), a = u(a, "property", "og:description", n), a = u(a, "property", "og:image", r), a = u(a, "property", "og:type", "website"), a = u(a, "name", "twitter:card", "summary_large_image"), a = u(a, "name", "twitter:title", t), a = u(a, "name", "twitter:description", n), a = u(a, "name", "twitter:image", r), a;
|
|
37
52
|
}
|
|
38
53
|
return t({ region: a }, async (e, t) => {
|
|
39
|
-
let a = Date.now();
|
|
54
|
+
let a = Date.now(), o = e.path, s = new URL(e.url, n), l = s.searchParams;
|
|
40
55
|
try {
|
|
41
|
-
let n =
|
|
42
|
-
for (let
|
|
43
|
-
let
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
56
|
+
let n = r;
|
|
57
|
+
for (let t of i) {
|
|
58
|
+
let r = o.match(t.pattern);
|
|
59
|
+
if (!r) continue;
|
|
60
|
+
let i = r[1] ?? r[0];
|
|
61
|
+
try {
|
|
62
|
+
let a = await t.resolve(i, {
|
|
63
|
+
req: e,
|
|
64
|
+
pathname: o,
|
|
65
|
+
searchParams: l,
|
|
66
|
+
match: r
|
|
67
|
+
});
|
|
68
|
+
if (a) {
|
|
69
|
+
n = a;
|
|
48
70
|
break;
|
|
49
71
|
}
|
|
72
|
+
} catch (e) {
|
|
73
|
+
console.error(`[SSRDynamicOG] Failed to resolve "${o}${s.search}" with pattern ${t.pattern}:`, e);
|
|
50
74
|
}
|
|
51
75
|
}
|
|
52
|
-
let
|
|
53
|
-
console.log(`[SSRDynamicOG] ${
|
|
76
|
+
let u = d(await c(), n.title, n.description, n.image);
|
|
77
|
+
console.log(`[SSRDynamicOG] ${o}${s.search} → ${n.title} (${Date.now() - a}ms)`), t.setHeader("Content-Type", "text/html; charset=utf-8"), t.status(200).send(u);
|
|
54
78
|
} catch (e) {
|
|
55
79
|
console.error("[SSRDynamicOG] error:", e), t.redirect(302, n);
|
|
56
80
|
}
|