Skip to content

Commit

Permalink
feat(edge): Inject JS code into 3rd party landing pages
Browse files Browse the repository at this point in the history
  • Loading branch information
koistya committed Jun 14, 2023
1 parent 09741db commit 7f07628
Show file tree
Hide file tree
Showing 11 changed files with 159 additions and 14 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
.* text eol=lf
*.css text eol=lf
*.html text eol=lf
*.ejs text eol=lf
*.hbs text eol=lf
*.js text eol=lf
*.json text eol=lf
*.md text eol=lf
Expand Down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,5 @@
# Misc
/.husky
*.hbs
*.ejs

21 changes: 21 additions & 0 deletions edge/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ declare type Bindings = {
FIREBASE_APP_ID: string;
FIREBASE_API_KEY: string;
FIREBASE_AUTH_DOMAIN: string;
GA_MEASUREMENT_ID: string;
__STATIC_CONTENT: KVNamespace;
};

Expand All @@ -25,3 +26,23 @@ declare type Env = {
};

declare function getMiniflareBindings<T = Bindings>(): T;

declare module "*.ejs" {
/**
* Generates HTML markup from an EJS template.
*
* @param locals an object of data to be passed into the template.
* @param escape callback used to escape variables
* @param include callback used to include files at runtime with `include()`
* @param rethrow callback used to handle and rethrow errors
*
* @return Return type depends on `Options.async`.
*/
const fn: (
locals?: Data,
escape?: EscapeCallback,
include?: IncludeCallback,
rethrow?: RethrowCallback,
) => string;
export default fn;
}
2 changes: 2 additions & 0 deletions edge/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import "./routes/firebase";
import "./routes/api";
// Register `/echo` route handler (debugging)
import "./routes/echo";
// Register `*` route handler for landing pages
import "./routes/landing";
// Register `*` static assets handler (HTML, CSS, JS, etc.)
import "./routes/assets";

Expand Down
2 changes: 2 additions & 0 deletions edge/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@
},
"dependencies": {
"@hono/zod-validator": "^0.1.3",
"ejs": "^3.1.9",
"hono": "^3.2.3",
"jose": "^4.14.4",
"web-auth-library": "^1.0.3",
"zod": "^3.21.4"
},
"devDependencies": {
"@cloudflare/workers-types": "^4.20230518.0",
"@types/ejs": "^3.1.2",
"@types/node": "^18.16.16",
"happy-dom": "^9.20.3",
"toml": "^3.0.0",
Expand Down
12 changes: 0 additions & 12 deletions edge/routes/assets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import assetManifest from "__STATIC_CONTENT_MANIFEST";
import { serveStatic } from "hono/cloudflare-workers";
import { getCookie } from "hono/cookie";
import { getMimeType } from "hono/utils/mime";
import { app } from "../core/app";

Expand All @@ -19,17 +18,6 @@ const fallback = serveStatic({ path: "/index.html", manifest });
export const handler = app.use("*", async (ctx, next) => {
const url = new URL(ctx.req.url);

// Indicates whether the user was previously authenticated
const isAuthenticated = getCookie(ctx, "auth") === "1";

if (url.pathname === "/" && isAuthenticated) {
// TODO: Render the app dashboard
// url.pathname === "/dashboard";
} else {
// TODO: Render the app landing page
// return await fetch("https://example.framer.app/", ctx.req.raw);
}

// Alternatively, import the list of routes from the `app` package
const isKnownRoute = [
"",
Expand Down
46 changes: 46 additions & 0 deletions edge/routes/landing.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* SPDX-FileCopyrightText: 2014-present Kriasoft */
/* SPDX-License-Identifier: MIT */

import { getCookie } from "hono/cookie";
import { app } from "../core/app";
import snippet from "../views/landing.ejs";

// Serve landing pages
app.use("*", async (ctx, next) => {
const url = new URL(ctx.req.url);

if (!["/", "/about", "/home"].includes(url.pathname)) {
return next();
}

// Indicates whether the user was previously authenticated
const isAuthenticated = getCookie(ctx, "auth") === "1";

// Do not serve the home landing page to authenticated users
if (url.pathname === "/" && isAuthenticated) {
return next();
}

const res = await fetch("https://example.framer.app/", ctx.req.raw);

return new HTMLRewriter()
.on("link", {
element(el) {
if (el.getAttribute("rel") === "icon") {
el.setAttribute("href", "/favicon.ico");
}
},
})
.on("body", {
element(el) {
el.onEndTag((tag) => {
try {
tag.before(snippet(ctx.env), { html: true });
} catch (err) {
console.error(err);
}
});
},
})
.transform(res.clone());
});
2 changes: 1 addition & 1 deletion edge/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
"types": ["@cloudflare/workers-types", "vite/client"],
"outDir": "../.cache/typescript-edge"
},
"include": ["**/*.ts", "**/*.json"],
"include": ["**/*.ts", "**/*.json", "**/*.ejs"],
"exclude": ["dist/**/*", "vite.config.ts"]
}
31 changes: 31 additions & 0 deletions edge/views/landing.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<script type="module">
import { initializeApp, getApp } from "https://www.gstatic.com/firebasejs/9.22.2/firebase-app.js";
import { getAuth } from "https://www.gstatic.com/firebasejs/9.22.2/firebase-auth.js";
const app = initializeApp({
projectId: "<%- env.GOOGLE_CLOUD_PROJECT %>",
appId: "<%- env.FIREBASE_APP_ID %>",
apiKey: "<%- env.FIREBASE_API_KEY %>",
authDomain: "<%- env.FIREBASE_AUTH_DOMAIN %>",
});
const auth = getAuth(app);
auth.onAuthStateChanged((user) => {
if (user) {
console.log("User is signed in");
} else {
console.log("User is signed out");
}
});
</script>

<script async src="https://www.googletagmanager.com/gtag/js?id=<%- env.GA_MEASUREMENT_ID %>"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag("js", new Date());
gtag("config", "<%- env.GA_MEASUREMENT_ID %>");
</script>
2 changes: 2 additions & 0 deletions edge/wrangler.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ GOOGLE_CLOUD_PROJECT = "${GOOGLE_CLOUD_PROJECT}"
FIREBASE_APP_ID = "${FIREBASE_APP_ID}"
FIREBASE_API_KEY = "${FIREBASE_API_KEY}"
FIREBASE_AUTH_DOMAIN = "${FIREBASE_AUTH_DOMAIN}"
GA_MEASUREMENT_ID = "${GA_MEASUREMENT_ID}"

# [secrets]
# GOOGLE_CLOUD_CREDENTIALS
Expand All @@ -47,3 +48,4 @@ GOOGLE_CLOUD_PROJECT = "${GOOGLE_CLOUD_PROJECT}"
FIREBASE_APP_ID = "${FIREBASE_APP_ID}"
FIREBASE_API_KEY = "${FIREBASE_API_KEY}"
FIREBASE_AUTH_DOMAIN = "${FIREBASE_AUTH_DOMAIN}"
GA_MEASUREMENT_ID = "${GA_MEASUREMENT_ID}"
52 changes: 51 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2905,6 +2905,13 @@ __metadata:
languageName: node
linkType: hard

"@types/ejs@npm:^3.1.2":
version: 3.1.2
resolution: "@types/ejs@npm:3.1.2"
checksum: 884ac1937d2e75ea90092934c13e588601a04d9a783bb4587a63e786b61d5079568408513a792e4b870bab60a3bb71240929b96e9a42e35fdad0ff7ef32a0a3e
languageName: node
linkType: hard

"@types/express-serve-static-core@npm:^4.17.33":
version: 4.17.35
resolution: "@types/express-serve-static-core@npm:4.17.35"
Expand Down Expand Up @@ -4013,6 +4020,13 @@ __metadata:
languageName: node
linkType: hard

"async@npm:^3.2.3":
version: 3.2.4
resolution: "async@npm:3.2.4"
checksum: 9719e38d24e9922c255ee9ae925fb668ef52243f9866a1b59e423a3bb6150a886b3c37287348ceefa09cd3f6fa1a29dcc770eeb70642acb13674363b2d5b2b21
languageName: node
linkType: hard

"asynckit@npm:^0.4.0":
version: 0.4.0
resolution: "asynckit@npm:0.4.0"
Expand Down Expand Up @@ -4530,7 +4544,7 @@ __metadata:
languageName: node
linkType: hard

"chalk@npm:^4.0.0, chalk@npm:^4.1.0, chalk@npm:^4.1.2":
"chalk@npm:^4.0.0, chalk@npm:^4.0.2, chalk@npm:^4.1.0, chalk@npm:^4.1.2":
version: 4.1.2
resolution: "chalk@npm:4.1.2"
dependencies:
Expand Down Expand Up @@ -5454,7 +5468,9 @@ __metadata:
dependencies:
"@cloudflare/workers-types": "npm:^4.20230518.0"
"@hono/zod-validator": "npm:^0.1.3"
"@types/ejs": "npm:^3.1.2"
"@types/node": "npm:^18.16.16"
ejs: "npm:^3.1.9"
happy-dom: "npm:^9.20.3"
hono: "npm:^3.2.3"
jose: "npm:^4.14.4"
Expand All @@ -5475,6 +5491,17 @@ __metadata:
languageName: node
linkType: hard

"ejs@npm:^3.1.9":
version: 3.1.9
resolution: "ejs@npm:3.1.9"
dependencies:
jake: "npm:^10.8.5"
bin:
ejs: bin/cli.js
checksum: c970131c2c9831dc260d2420055c1e69500a75a460301cf3cac3bab8ff19cb15de2fcc2c695051420b123cd9f8c20c2a18154916d3494b4870ea68a0d677ac12
languageName: node
linkType: hard

"electron-to-chromium@npm:^1.4.411":
version: 1.4.417
resolution: "electron-to-chromium@npm:1.4.417"
Expand Down Expand Up @@ -6744,6 +6771,15 @@ __metadata:
languageName: node
linkType: hard

"filelist@npm:^1.0.4":
version: 1.0.4
resolution: "filelist@npm:1.0.4"
dependencies:
minimatch: "npm:^5.0.1"
checksum: f24e711620c5f75b3016e09f2dce86f6598237349c0ba825dc2074f4efa50f450bfba4dbdca2592a8ba60c4a6300ddf9a9dd89d25e9baa5c68837c0c549267f5
languageName: node
linkType: hard

"fill-range@npm:^7.0.1":
version: 7.0.1
resolution: "fill-range@npm:7.0.1"
Expand Down Expand Up @@ -8486,6 +8522,20 @@ __metadata:
languageName: node
linkType: hard

"jake@npm:^10.8.5":
version: 10.8.7
resolution: "jake@npm:10.8.7"
dependencies:
async: "npm:^3.2.3"
chalk: "npm:^4.0.2"
filelist: "npm:^1.0.4"
minimatch: "npm:^3.1.2"
bin:
jake: bin/cli.js
checksum: 92991ae6bcb5e0889e68e745a667992fdc4bf17e62dfda1d01db535e494347f20d9d47b9bcd31f149dcd96aad2ccd9e2994f917c33b9c6adc124e8730135137d
languageName: node
linkType: hard

"jiti@npm:^1.18.2":
version: 1.18.2
resolution: "jiti@npm:1.18.2"
Expand Down

0 comments on commit 7f07628

Please sign in to comment.