@abcnews/dev-proxy
Advanced tools
Comparing version 1.1.0 to 1.2.0
@@ -1,2 +0,2 @@ | ||
export declare enum RESOLUTION_REASONS { | ||
declare enum RESOLUTION_REASONS { | ||
'DEV_ENV' = 0, | ||
@@ -6,4 +6,8 @@ 'IN_PRODUCTION' = 1, | ||
'BAD_SCRIPT_URL' = 3, | ||
'OTHER' = 4 | ||
'OTHER' = 4, | ||
'NO_PROXY_SCRIPT' = 5 | ||
} | ||
export declare const proxy: (project: string) => Promise<number>; | ||
declare const domainMatcher: RegExp; | ||
declare const proxy: (project: string) => Promise<number>; | ||
export { RESOLUTION_REASONS, domainMatcher, proxy }; |
@@ -0,8 +1,140 @@ | ||
"use strict"; | ||
var __defProp = Object.defineProperty; | ||
var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
var __getOwnPropNames = Object.getOwnPropertyNames; | ||
var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
var __esm = (fn, res) => function __init() { | ||
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res; | ||
}; | ||
var __export = (target, all) => { | ||
for (var name in all) | ||
__defProp(target, name, { get: all[name], enumerable: true }); | ||
}; | ||
var __copyProps = (to, from, except, desc) => { | ||
if (from && typeof from === "object" || typeof from === "function") { | ||
for (let key of __getOwnPropNames(from)) | ||
if (!__hasOwnProp.call(to, key) && key !== except) | ||
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
} | ||
return to; | ||
}; | ||
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
'use strict' | ||
// src/main.ts | ||
var main_exports = {}; | ||
__export(main_exports, { | ||
init: () => init, | ||
manager: () => manager | ||
}); | ||
var init, listener, manager; | ||
var init_main = __esm({ | ||
"src/main.ts"() { | ||
"use strict"; | ||
init_src(); | ||
init = (project) => { | ||
return new Promise((resolve, reject) => { | ||
if (process.env.NODE_ENV === "development") { | ||
return resolve(0 /* DEV_ENV */); | ||
} | ||
let src; | ||
try { | ||
src = localStorage.getItem("proxy_" + project); | ||
} catch (e) { | ||
src = null; | ||
} | ||
if (src === null || src.trim() === "") { | ||
return resolve(5 /* NO_PROXY_SCRIPT */); | ||
} | ||
let url; | ||
try { | ||
url = new URL(src); | ||
} catch (e) { | ||
return resolve(3 /* BAD_SCRIPT_URL */); | ||
} | ||
if (url.hostname.match(domainMatcher) === null) { | ||
return resolve(2 /* NON_ABC_SCRIPT */); | ||
} | ||
const scr = document.createElement("script"); | ||
scr.src = src; | ||
document.head.appendChild(scr); | ||
const msg = "[dev-proxy] Loaded script: " + src + ` (${project})`; | ||
console.info(msg); | ||
return reject(msg); | ||
}); | ||
}; | ||
listener = (event) => { | ||
if (event.altKey && event.code === "KeyM") { | ||
let modified = false; | ||
const project = prompt( | ||
"Project", | ||
Array.from(document.querySelectorAll("script[src]")).map((script) => { | ||
var _a; | ||
const m = (_a = script.getAttribute("src")) == null ? void 0 : _a.match(/news-projects\/([\w-]+)/); | ||
return m ? m[1] : false; | ||
}).filter((d) => !!d).join(",") | ||
); | ||
if (!project) | ||
return; | ||
project.split(",").forEach((project2) => { | ||
const replace = prompt( | ||
"Replacement for " + project2, | ||
localStorage["proxy_" + project2] | ||
); | ||
if (replace === localStorage["proxy_" + project2]) | ||
return; | ||
modified = true; | ||
localStorage["proxy_" + project2] = replace; | ||
}); | ||
if (modified) | ||
document.location.reload(); | ||
} | ||
}; | ||
manager = () => { | ||
if (window.__DEV_PROXY__) | ||
return; | ||
document.addEventListener("keydown", listener); | ||
window.__DEV_PROXY__ = true; | ||
}; | ||
} | ||
}); | ||
if (process.env.NODE_ENV === 'production') { | ||
module.exports = require('./dev-proxy.cjs.production.min.js') | ||
} else { | ||
module.exports = require('./dev-proxy.cjs.development.js') | ||
} | ||
// src/index.ts | ||
var src_exports = {}; | ||
__export(src_exports, { | ||
RESOLUTION_REASONS: () => RESOLUTION_REASONS, | ||
domainMatcher: () => domainMatcher, | ||
proxy: () => proxy | ||
}); | ||
module.exports = __toCommonJS(src_exports); | ||
var RESOLUTION_REASONS, domainMatcher, proxy; | ||
var init_src = __esm({ | ||
"src/index.ts"() { | ||
RESOLUTION_REASONS = /* @__PURE__ */ ((RESOLUTION_REASONS2) => { | ||
RESOLUTION_REASONS2[RESOLUTION_REASONS2["DEV_ENV"] = 0] = "DEV_ENV"; | ||
RESOLUTION_REASONS2[RESOLUTION_REASONS2["IN_PRODUCTION"] = 1] = "IN_PRODUCTION"; | ||
RESOLUTION_REASONS2[RESOLUTION_REASONS2["NON_ABC_SCRIPT"] = 2] = "NON_ABC_SCRIPT"; | ||
RESOLUTION_REASONS2[RESOLUTION_REASONS2["BAD_SCRIPT_URL"] = 3] = "BAD_SCRIPT_URL"; | ||
RESOLUTION_REASONS2[RESOLUTION_REASONS2["OTHER"] = 4] = "OTHER"; | ||
RESOLUTION_REASONS2[RESOLUTION_REASONS2["NO_PROXY_SCRIPT"] = 5] = "NO_PROXY_SCRIPT"; | ||
return RESOLUTION_REASONS2; | ||
})(RESOLUTION_REASONS || {}); | ||
domainMatcher = /^(www|newsapp)\.abc\.net\.au$/; | ||
proxy = (project) => new Promise((resolve) => { | ||
if (document.location.host.match(domainMatcher) && !document.location.pathname.match(/news-projects/)) { | ||
return resolve(1 /* IN_PRODUCTION */); | ||
} | ||
Promise.resolve().then(() => (init_main(), main_exports)).then(({ manager: manager2, init: init2 }) => { | ||
manager2(); | ||
resolve(init2(project)); | ||
}); | ||
}); | ||
} | ||
}); | ||
init_src(); | ||
// Annotate the CommonJS export names for ESM import in node: | ||
0 && (module.exports = { | ||
RESOLUTION_REASONS, | ||
domainMatcher, | ||
proxy | ||
}); | ||
//# sourceMappingURL=index.js.map |
{ | ||
"version": "1.1.0", | ||
"version": "1.2.0", | ||
"license": "MIT", | ||
@@ -11,18 +11,18 @@ "main": "dist/index.js", | ||
"engines": { | ||
"node": ">=14" | ||
"node": ">=16" | ||
}, | ||
"scripts": { | ||
"start": "tsdx watch", | ||
"build": "tsdx build", | ||
"test": "tsdx test", | ||
"lint": "tsdx lint", | ||
"prepare": "tsdx build", | ||
"size": "size-limit", | ||
"start": "tsup src/index.ts --dts --sourcemap --format esm,cjs --watch", | ||
"build": "tsup src/index.ts --dts --sourcemap --format esm,cjs", | ||
"test": "jest --coverage", | ||
"lint": "eslint src", | ||
"prepare": "husky install", | ||
"prepublishOnly": "npm run build", | ||
"size": "npm run build && size-limit", | ||
"analyze": "size-limit --why", | ||
"release": "np" | ||
}, | ||
"peerDependencies": {}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "tsdx lint" | ||
"pre-commit": "npm run lint" | ||
} | ||
@@ -38,21 +38,28 @@ }, | ||
"author": "Simon Elvery", | ||
"module": "dist/dev-proxy.esm.js", | ||
"module": "dist/index.mjs", | ||
"size-limit": [ | ||
{ | ||
"path": "dist/dev-proxy.cjs.production.min.js", | ||
"limit": "10 KB" | ||
"path": "dist/index.mjs", | ||
"limit": "1 KB" | ||
}, | ||
{ | ||
"path": "dist/dev-proxy.esm.js", | ||
"limit": "10 KB" | ||
"path": "dist/index.js", | ||
"limit": "1.5 KB" | ||
} | ||
], | ||
"devDependencies": { | ||
"@size-limit/preset-small-lib": "^4.11.0", | ||
"husky": "^6.0.0", | ||
"@size-limit/esbuild-why": "^8.2.4", | ||
"@size-limit/preset-small-lib": "^8.2.4", | ||
"@types/jest": "^29.5.1", | ||
"@typescript-eslint/eslint-plugin": "^5.59.2", | ||
"eslint": "^8.39.0", | ||
"husky": "^8.0.3", | ||
"jest": "^29.5.0", | ||
"jest-environment-jsdom": "^29.5.0", | ||
"np": "^7.5.0", | ||
"size-limit": "^4.11.0", | ||
"tsdx": "^0.14.1", | ||
"size-limit": "^8.2.4", | ||
"ts-jest": "^29.1.0", | ||
"tslib": "^2.2.0", | ||
"typescript": "^4.3.2" | ||
"tsup": "^6.7.0", | ||
"typescript": "^5.0.4" | ||
}, | ||
@@ -59,0 +66,0 @@ "publishConfig": { |
@@ -19,4 +19,15 @@ # Dev script proxy | ||
## How does it work? | ||
The `proxy` function returns a promise that will either: | ||
- **resolve successfully**, indicating that the script initialisation should go ahead (i.e. the `.then(init)` part of the above implementation example), or | ||
- **be rejected**, indicating that an alternative script has been successfully identified and added to the document and the init function should not be run. | ||
For the `proxy` function to successfully identify a script to run instead a few criteria need to be met: | ||
- The script importing the `proxy` function should not have a `NODE_ENV` of 'development' (this prevents infinite loops when this `proxy` function is used on a dev server. | ||
- The script should not be running on a production URL. | ||
- `localStorage` must contain an entry identifying a suitable replacement hosted on an ABC url (including `localhost` aliases that include `abc.net.au`). | ||
## Bookmarklet | ||
You can use [this bookmarklet](<https://bookmarklet-topaz.vercel.app/?name=Proxy%20news-project&source=!function()%7Bconst%20t%3Dprompt(%22Project%22%2CArray.from(document.querySelectorAll(%22script%5Bsrc%5D%22)).map((t%3D%3E%7Bconst%20r%3Dt.getAttribute(%22src%22).match(%2Fnews-projects%5C%2F(%5B%5Cw-%5D%2B)%2F)%3Breturn!!r%26%26r%5B1%5D%7D)).filter((t%3D%3E!!t)).join(%22%2C%22))%3Bt%26%26t.split(%22%2C%22).forEach((t%3D%3E%7Bconst%20r%3Dprompt(%22Replacement%20for%20%22%2Bt)%3Br%26%26(localStorage%5B%22proxy_%22%2Bt%5D%3Dr)%7D))%7D()%3B>) to help setup the config. |
@@ -7,47 +7,24 @@ export enum RESOLUTION_REASONS { | ||
'OTHER', | ||
'NO_PROXY_SCRIPT', | ||
} | ||
export const domainMatcher = /^(www|newsapp)\.abc\.net\.au$/; | ||
// Checks if a proxy is requested for this project and loads it if required. | ||
// The returned promise will only resolve if no proxy is loaded. | ||
export const proxy = (project: string) => | ||
new Promise<number>((resolve, reject) => { | ||
// If we're already in a dev environment, there's nothing to do here. | ||
if (process.env.NODE_ENV === 'development') | ||
return resolve(RESOLUTION_REASONS.DEV_ENV); | ||
new Promise<number>((resolve) => { | ||
// Never run on live/production. | ||
if ( | ||
document.location.host === 'www.abc.net.au' && | ||
document.location.host.match(domainMatcher) && | ||
!document.location.pathname.match(/news-projects/) | ||
) | ||
) { | ||
return resolve(RESOLUTION_REASONS.IN_PRODUCTION); | ||
let src: string | null; | ||
try { | ||
src = localStorage.getItem('proxy_' + project); | ||
} catch (e) { | ||
src = null; | ||
} | ||
if (src) { | ||
let url: URL; | ||
try { | ||
url = new URL(src); | ||
} catch (e) { | ||
return resolve(RESOLUTION_REASONS.BAD_SCRIPT_URL); | ||
} | ||
if (url.hostname.match(/abc\.net\.au$/) === null) { | ||
return resolve(RESOLUTION_REASONS.NON_ABC_SCRIPT); | ||
} | ||
const scr = document.createElement('script'); | ||
scr.src = src; | ||
document.head.appendChild(scr); | ||
const msg = '[dev-proxy] Loaded script: ' + src + ` (${project})`; | ||
console.info(msg); | ||
return reject(msg); | ||
} | ||
resolve(RESOLUTION_REASONS.OTHER); | ||
// Load in a cheaky management keyboard shortcut | ||
import('./main').then(({ manager, init }) => { | ||
manager(); | ||
resolve(init(project)); | ||
}); | ||
}); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
93818
52
1167
33
14
8