Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ const podlet = new Podlet({
name: 'myPodlet',
version: '1.3.1',
pathname: '/',
development: true,
isLocalhost: true,
});

// create a new express app instance
Expand Down Expand Up @@ -84,7 +84,7 @@ const podlet = new Podlet(options);
| content | `string` | `/` | |
| fallback | `string` | | |
| logger | `object` | | |
| development | `boolean` | `false` | |
| isLocalhost | `boolean` | `false` | |
| useShadowDOM | `boolean` | `false` | |

#### name
Expand Down Expand Up @@ -245,16 +245,16 @@ _Example:_

```js
const podlet = new Podlet({
logger: console;
logger: console,
});
```

Under the hood [abslog] is used to abstract out logging. Please see [abslog] for
further details.

#### development
#### isLocalhost

Turns development mode on or off. See the section about development mode.
Turns development mode on or off. See the section about [development mode](#development-mode).

#### useShadowDOM

Expand Down Expand Up @@ -315,7 +315,7 @@ used directly by library users to create podlet servers.

What it does:

- Handles detection of development mode and sets appropriate defaults
- Handles detection of [development mode](#development-mode) and sets appropriate defaults
- Runs context deserializing on the incoming request and sets a context object at `HttpIncoming.context`.

Returns an [HttpIncoming] object.
Expand Down Expand Up @@ -883,7 +883,7 @@ app.listen(7100);
Method on the `http.ServerResponse` object for sending an HTML fragment. Calls
the send / write method on the `http.ServerResponse` object.

When in development mode this method will wrap the provided fragment in a
When in [development mode](#development-mode) this method will wrap the provided fragment in a
default HTML document before dispatching. When not in development mode, this
method will just dispatch the fragment.

Expand All @@ -897,7 +897,7 @@ app.get(podlet.content(), (req, res) => {

### .defaults(context)

Alters the default context set when in development mode.
Alters the default context set when in [development mode](#development-mode).

By default this context has the following shape:

Expand Down Expand Up @@ -946,11 +946,11 @@ podlet.defaults({
```

N.B. The default development mode context will only be appended to the response
when the constructor argument `development` is set to `true`.
when the constructor argument `isLocalhost` is set to `true`.

### .view(template)

Override the default encapsulating HTML document when in development mode.
Override the default encapsulating HTML document when in [development mode](#development-mode).

Takes a function in the following shape:

Expand Down Expand Up @@ -1028,7 +1028,7 @@ podlet without either an encapsulating HTML document or a Podium context that
the podlet might need to function properly.

To solve this it is possible to switch a podlet to development mode by setting
the `development` argument in the constructor to `true`.
the `isLocalhost` argument in the constructor to `true`.

When in development mode a default context on the HTTP response will be set and
an encapsulating HTML document will be provided (so long as `res.podiumSend()`
Expand All @@ -1051,7 +1051,7 @@ _Example of turning on development mode only in local development:_

```js
const podlet = new Podlet({
development: process.env.NODE_ENV !== 'production';
isLocalhost: process.env.NODE_ENV !== 'production';
});
```

Expand Down
67 changes: 30 additions & 37 deletions lib/podlet.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ const pkg = JSON.parse(pkgJson);
const { template } = utils;

/**
* @typedef {Object} PodletOptions
* @property {string} name - (required) podlet name
* @property {string} version - (required) podlet version
* @property {string} pathname - (required) podlet pathname
* @property {string} [manifest="/manifest.json"] - path where the podlet manifest file is served from (default '/manifest.json')
* @property {string} [content="/"] - path where the podlet content HTML markup is served from (default '/')
* @property {string} [fallback=""] - path where the podlet fallback HTML markup is served from (default '/fallback')
* @property {boolean} [development=false] - a boolean flag that, when true, enables additional development setup (default false)
* @property {boolean} [useShadowDOM=false] - a boolean flag that, when true, enables the use of ShadowDOM (default false)
* @property {import("abslog").AbstractLoggerOptions} [logger] - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
* @property {import("@podium/proxy").PodiumProxyOptions} [proxy] - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details.
*
* @typedef {{ debug: 'true' | 'false', locale: string, deviceType: string, requestedBy: string, mountOrigin: string, mountPathname: string, publicPathname: string }} PodletContext
* @typedef {{ as?: string | false | null, crossorigin?: string | null | boolean, disabled?: boolean | '' | null, hreflang?: string | false | null, title?: string | false | null, media?: string | false | null, rel?: string | false | null, type?: string | false | null, value: string | false | null, strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom", scope?: "content" | "fallback" | "all", [key: string]: any }} AssetCssLike
* @typedef {{ value: string | null, crossorigin?: string | null | boolean, type?: string | null | false, integrity?: string | null | false, referrerpolicy?: string | null | false, nomodule?: boolean | null | '', async?: boolean | null | '', defer?: boolean | null | '', data?: {[key: string]: string} | Array<{ key: string; value: string }>, strategy?: "beforeInteractive" | "afterInteractive" | "lazy" | "shadow-dom", scope?: "content" | "fallback" | "all" | "shadow-dom", [key: string]: any }} AssetJsLike
Expand Down Expand Up @@ -106,19 +94,33 @@ export default class PodiumPodlet {
version = '';

/**
* The podlet development property (set in the constructor)
* @deprecated Use {@link isLocalhost}
*/
get development() {
return this.isLocalhost;
}

/**
* @deprecated Use {@link isLocalhost}
* @param {boolean} value
*/
set development(value) {
this.isLocalhost = value;
}

/**
* Used to make podlet development simple without the need to run a layout server locally
* Do not run a podlet in development mode when deploying to production.
* Do not run a podlet with this turned on when deploying to production.
*
* @see https://podium-lib.io/docs/api/podlet/#development
* @see https://podium-lib.io/docs/api/podlet/#development-mode
*
* @example ```js
* const podlet = new Podlet({ development: true, ... });
* podlet.development // true
* const podlet = new Podlet({ isLocalhost: true, ... });
* podlet.isLocalhost // true
* ```
*/
development = false;
isLocalhost = false;

/**
* A logger. The abstract logger "Abslog" is used to make it possible to provide different kinds of loggers.
Expand Down Expand Up @@ -207,7 +209,7 @@ export default class PodiumPodlet {

/**
* An object containing a set of Podium context values configured for podlet development.
* This is necessary when the podlet is in development mode because requests do not come from a layout (which is what normally sends the context information)
* This is necessary when the podlet is in development mode (`isLocalhost: true`) because requests do not come from a layout (which is what normally sends the context information)
* These base context values can be overridden by providing a default context using the podlet.defaults() method
* in which case the baseContext and the defaultContext will be merged together to provide the development context object.
* This is not used at all when the podlet is not in development mode or when it is in development mode but the request to the podlet comes from a Podium layout.
Expand Down Expand Up @@ -303,21 +305,10 @@ export default class PodiumPodlet {
* Creates a new instance of a Podium podlet which can be used in conjunction with your framework of choice to build podlet server apps.
* `name`, `version` and `pathname` constructor arguments are required. All other options are optional.
*
* * `name` - podlet name (**required**)
* * `version` - podlet version (**required**)
* * `pathname` - podlet pathname (**required**)
* * `manifest` - path where the podlet manifest file is served from (**default** `'/manifest.json'`)
* * `content` - path where the podlet content HTML markup is served from (**default** `'/'`)
* * `fallback` - path where the podlet fallback HTML markup is served from (**default** `'/fallback'`)
* * `development` - a boolean flag that, when true, enables additional development setup (**default** `false`)
* * `useShadowDOM` - a boolean flag that, when true, enables the use of declarative ShadowDOM in the podlet (**default** `false`)
* * `logger` - a logger to use when provided. Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (**default** `null`)
* * `proxy` - options that can be provided to configure the @podium/proxy instance used by the podlet. See that module for details. (**default**: `{}`)
*
* @see https://podium-lib.io/docs/api/podlet/#constructor
* @see https://podium-lib.io/docs/podlet/getting_started
*
* @param {PodletOptions} options
* @param {import("../types/podium.js").PodletOptions} options
*
* @example
* ```
Expand All @@ -332,7 +323,8 @@ export default class PodiumPodlet {
fallback = '',
content = '/',
logger = undefined,
development = false,
isLocalhost = false,
development,
proxy = {},
useShadowDOM = false,
}) {
Expand Down Expand Up @@ -373,7 +365,8 @@ export default class PodiumPodlet {
this.contentRoute = this.#sanitize(content);
this.fallbackRoute = this.#sanitize(fallback);
this.log = abslog(logger);
this.development = development;
this.isLocalhost =
typeof development !== 'undefined' ? development : isLocalhost;
this.httpProxy = new Proxy({
pathname: this.#pathname,
logger: this.log,
Expand Down Expand Up @@ -712,7 +705,7 @@ export default class PodiumPodlet {

this.proxyRoutes[name] = target;

if (this.development) {
if (this.isLocalhost) {
// @ts-ignore
this.httpProxy.register(this.name, this.toJSON());
}
Expand All @@ -721,7 +714,7 @@ export default class PodiumPodlet {
}

/**
* Method to alter the default context set when in development mode.
* Method to alter the default context set when in development mode (`isLocalhost: true`).
* In a production setup, this is not necessary since the context values are sent to the podlet from the layout.
* By default, the context will contain the following context values, all of which can be overridden.
*
Expand Down Expand Up @@ -753,7 +746,7 @@ export default class PodiumPodlet {
}

/**
* Method to set a Podium document template to be used when the podlet is in development mode.
* Method to set a Podium document template to be used when the podlet is in development mode (`isLocalhost: true`).
* Must be used in conjunction with with the `.podiumSend()` method or the `podlet.render()` in the content/fallback route to have any effect.
* Has no effect when the podlet is not in development mode or if a request to the podlet comes from a Podium layout.
*
Expand Down Expand Up @@ -910,7 +903,7 @@ export default class PodiumPodlet {
* Method for processing an incoming HTTP request. This method is intended to be used to implement support for multiple HTTP frameworks and in most cases will not need to be used directly by podlet developers when creating podlet servers.
*
* What it does:
* * Handles detection of development mode and sets the appropriate defaults
* * Handles detection of development mode (`isLocalhost: true`) and sets the appropriate defaults
* * Runs context deserializing on the incoming request and sets a context object at HttpIncoming.context.
* * Returns an HttpIncoming object.
*
Expand Down Expand Up @@ -938,7 +931,7 @@ export default class PodiumPodlet {
) {
incoming.development = false;
} else {
incoming.development = this.development;
incoming.development = this.isLocalhost;
}

// Append development context
Expand Down
28 changes: 28 additions & 0 deletions tests/podlet.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,34 @@ tap.test(
},
);

tap.test(
'.defaults() - constructor argument "isLocalhost" is to "true" - should append a default context to "res.locals"',
async (t) => {
const podlet = new Podlet({
name: 'foo',
version: 'v1.0.0',
pathname: '/',
isLocalhost: true,
});
const server = new FakeExpressServer(podlet);
const address = await server.listen();
const result = await server.get();

t.equal(result.response.podium.context.debug, 'false');
t.equal(result.response.podium.context.locale, 'en-US');
t.equal(result.response.podium.context.deviceType, 'desktop');
t.equal(result.response.podium.context.requestedBy, 'foo');
t.equal(result.response.podium.context.mountOrigin, address);
t.equal(result.response.podium.context.mountPathname, '/');
t.equal(
result.response.podium.context.publicPathname,
'/podium-resource/foo',
);

await server.close();
},
);

tap.test(
'.defaults() - set "context" argument where a key overrides one existing context value - should override default context value but keep rest untouched',
async (t) => {
Expand Down
44 changes: 44 additions & 0 deletions types/podium.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,47 @@ declare global {
}
}
}

export type PodletOptions = {
name: string;
version: string;
pathname: string;
/**
* Path where the podlet manifest file is served from.
* @default "/manifest.json"
*/
manifest?: string;
/**
* Path where the podlet content HTML markup is served from
* @default "/"
*/
content?: string;
/**
* - path where the podlet fallback HTML markup is served from
* @default "/fallback"
*/
fallback?: string;
/**
* Enables additional development setup such as rendering the podlet in a shared HTML document template.
* @default false
*/
isLocalhost?: boolean;
/**
* Enables additional development setup (default false)
* @deprecated Use {@link isLocalhost} for clarity
* @default false
*/
development?: boolean;
/**
* When true, enables the use of ShadowDOM to isolate the podlet CSS as much as possible.
*/
useShadowDOM?: boolean;
/**
* Can be the console object if console logging is desired but can also be any Log4j compatible logging object as well. Nothing is logged if no logger is provided. (default null)
*/
logger?: import("abslog").AbstractLoggerOptions;
/**
* Options that can be provided to configure the Podium proxy
*/
proxy?: import("@podium/proxy").PodiumProxyOptions;
};