npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@abcnews/env-utils

v4.0.0

Published

Utilities for identifying aspects of your code's execution environment and respectfully interacting with the DOM

Downloads

80

Readme

@abcnews/env-utils

Utilities for identifying aspects of your code's execution environment and respectfully interacting with the DOM.

You can identify the current environment's application, generation and tier (see API for what each of those are).

Each generation has its own assumptions about how and when we should modfy the DOM. Always ask for permission first, and listen for a notifications of that permission being revoked.

Usage

npm i @abcnews/env-utils

Assume we're using this module in a article rendered by Presentation Layer News Web on our Preview website

import {
  getApplication,
  getGeneration,
  getTier,
  requestDOMPermit,
} from '@abcnews/env-utils';

getApplication();
// > 'pln'

getGeneration();
// > 'pl'

getTier();
// > 'preview'

requestDOMPermit('article').then(() => {
  // It is now safe to modify the DOM tree below the <Decoy key="article"> PL compoonent
});

Note: use #start<name> and #end<name> inside a CoreMedia article to create a ranged decoy.

Development utils

Sometimes developing locally for the PL environment is difficult due to the DOM permit system that requestDOMPermit provides an interface for as it relies on events fired by Presentation Layer and the existence of some specific DOM elements.

There is an additional function exported from the library — mockDecoyActivationEvents — which can be used to mock the decoy events and make testing using a local test page easier.

Example usage:

import {
  requestDOMPermit,
  mockDecoyActivationEvents,
} from '@abcnews/env-utils';

if (process.env.NODE_ENV === 'development') {
  mockDecoyActivationEvents();
}

requestDOMPermit('key').then(/* you have a permit for 'key' */);

You will also need to add the DOM requestDOMPermit expects for decoys to your testing HTML. For example, a ranged decoy with the key 'key':

<div data-component="Decoy" data-key="key" data-clone="true">
  <p>
    All the stuff between here is inside the decoy and fair game after a DOM
    permit is granted.
  </p>
</div>

API

APPLICATIONS, GENERATIONS, & TIERS

Enumerated (named) applications, generations and tiers; useful for argument abstraction & logging.

import { APPLICATIONS, GENERATIONS, TIERS } from '@abcnews/env-utils';

console.log(APPLICATIONS);
// > {
//     P1M: 'p1m', // Phase 1 Mobile
//     P1S: 'p1s', // Phase 1 Standard
//     P2:  'p2',  // Phase 2
//     PLA: 'pla', // Presentation Layer ABC AMP
//     PLC: 'plc', // Presentation Layer Core
//     PLE: 'ple', // Presentation Layer Everyday
//     PLN: 'pln', // Presentation Layer News Web
//   }
console.log(GENERATIONS);
// > {
//     P1: 'p1', // Phase 1
//     P2: 'p2', // Phase 2
//     PL: 'pl', // Presentation Layer
//   }
console.log(TIERS);
// > {
//     LIVE: 'live',
//     PREVIEW: 'preview',
//   }

getApplication(): string | null

Return the environment's application (Phase 1 Mobile; Phase 1 Standard; Phase 2; Presentation Layer ABC AMP; Presentation Layer Core; Presentation Layer Everyday; Presentation Layer News Web) as a string value from the APPLICATIONS enum, or null if the application couldn't be determined.

import { APPLICATIONS, getApplication } from '@abcnews/env-utils';

getApplication();
// > 'pln'

getApplication() === APPLICATIONS.PLN;
// > true

Applications are currently determined by success/failure of selecting DOM nodes in the document, which hint at the technology used to render them on the server.

getGeneration(): string | null

Return the environment's generation (Phase 1; Phase 2; Presentation Layer) as a string value from the GENERATIONS enum, or null if the generation couldn't be determined.

import { GENERATIONS, getGeneration } from '@abcnews/env-utils';

getGeneration();
// > 'pl'

getGeneration() === GENERATIONS.PL;
// > true

Generations are currently determined by categorising detected applications.

getTier(): string | null

Return the environment's tier (Live; Preview) as a string value from the TIERS enum, or null if the tier couldn't be determined.

import { TIERS, getTier } from '@abcnews/env-utils';

getTier();
// > 'preview'

getTier() === TIERS.PREVIEW;
// > true

Tiers are currently determined by comparing window.location.hostname to domains that tiers are potentially served from.

requestDOMPermit(key: string, onRevokeHandler?: Function): Promise<true|HTMLElement[]>

Request a permit to modify the DOM.

This is advised before modifying the DOM on Presentation Layer generation applications (as they are controlled by React, and will almost certainly undo your own changes).

DOM modification is usually safe on older generation applications, but permits should be requested anyway, for the sake of consistency.

The key argument is used by Presentation Layer to activate its respective <Decoy> components.

An optional onRevokeHandler argument can be passed, which will be called if Presentation Layer chooses to deactivate <Decoy>s and restore their orignal DOM.

Note: key values may be any [a-z] string, but the Presentation Layer News Web application provides several pre-determined values, which this library exposes as DECOY_KEYS.

import { DECOY_KEYS, requestDOMPermit } from '@abcnews/env-utils';

requestDOMPermit(DECOY_KEYS.PAGE, () => {
  // It is no longer safe to modify the DOM tree below <Decoy listenKey="page"> PL compoonents
}).then(() => {
  // It is now safe to modify the DOM tree below <Decoy listenKey="page"> PL compoonents
});

The returned promise resolves differently depending on the GENERATION on which it's running. On Presentation Layer sites the promise will resolve with an array of HTMLElement references for all the nodes where the decoy was activated. On prior generations, it will resolve with true.

The promise will be rejected after 5 seconds if all expected decoys haven't been activated. Additionally, the library will attempt to undo any successful activations by sending another request to PL to deactivate decoys with the given key.

whenDOMReady(): Promise<void>

A promise that resolves when the DOM is ready. On Presentation Layer documents the DOM isn't considered ready until after the React tree is rehydrated.

whenOdysseyLoaded(): Promise<window.__ODYSSEY__>

A promise that resolves when Odyssey is finished loading. This will resolve with a reference to the Odyssey API.

Development

Everything you need should be in the npm scripts:

npm start
npm test
npm run release

Running tests requires some environment variables be set. The canonical version of these env vars are stored as secrets in GitHub, but if you need them to run tests locally, chat to one of the authors listed below.

Authors