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
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ coverage
.vscode
dist/
.tap
types/
types/*
!types/options.d.ts
13 changes: 7 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,13 @@ await eik.load();

### options

| option | default | type | required | details |
| ----------- | --------------- | --------- | -------- | ------------------------------------------------------------------------------------------------ |
| base | `null` | `string` | `false` | Base root to be used for returned asset files. |
| development | `false` | `boolean` | `false` | Set the module in development mode or not. |
| loadMaps | `false` | `boolean` | `false` | Specifies whether import maps defined in the config should be loaded from the Eik server or not. |
| path | `process.cwd()` | `string` | `false` | Path to directory containing an eik.json file or package.json with eik config. |
| option | default | type | required | details |
| ----------- | --------------- | --------- | -------- | ----------------------------------------------------------------------------------------------------------- |
| base | `null` | `string` | `false` | Base root to be used for returned asset files. |
| isLocalhost | `false` | `boolean` | `false` | Determines whether the client produces links to localhost (f. ex. during development) or to the Eik server. |
| development | `false` | `boolean` | `false` | (deprecated) Same as isLocalhost |
| loadMaps | `false` | `boolean` | `false` | Specifies whether import maps defined in the config should be loaded from the Eik server or not. |
| path | `process.cwd()` | `string` | `false` | Path to directory containing an eik.json file or package.json with eik config. |

## API

Expand Down
45 changes: 19 additions & 26 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,6 @@ const trimSlash = (value = "") => {
return value;
};

/**
* @typedef {object} Options
* @property {string} [base=null]
* @property {boolean} [development=false]
* @property {boolean} [loadMaps=false]
* @property {string} [path=process.cwd()]
*/

/**
* @typedef {object} ImportMap
* @property {Record<string, string>} imports
Expand All @@ -36,7 +28,7 @@ const trimSlash = (value = "") => {
* @example
* ```js
* // Serve a local version of a file from `./public`
* // in development and from Eik in production
* // on localhost and from Eik in any other environment.
* import path from "node:path";
* import Eik from "@eik/node-client";
* import fastifyStatic from "@fastify/static";
Expand All @@ -49,15 +41,15 @@ const trimSlash = (value = "") => {
* });
*
* const eik = new Eik({
* development: process.env.NODE_ENV === "development",
* isLocalhost: process.env.NODE_ENV === "development",
* base: "/public",
* });
*
* // load information from `eik.json` and the Eik server
* await eik.load();
*
* // when development is true script.value will be /public/script.js.
* // when development is false script.value will be
* // when isLocalhost is true script.value will be /public/script.js.
* // when isLocalhost is false script.value will be
* // https://{server}/pkg/{name}/{version}/script.js
* // where {server}, {name} and {version} are read from eik.json
* const script = eik.file("/script.js");
Expand All @@ -80,23 +72,25 @@ const trimSlash = (value = "") => {
* ```
*/
export default class Eik {
#development;
#isLocalhost;
#loadMaps;
#config;
#path;
#base;
#maps;

/**
* @param {Options} options
* @param {import("../types/options.js").Options} options
*/
constructor({
development = false,
isLocalhost = false,
development,
loadMaps = false,
base = "",
path = process.cwd(),
} = {}) {
this.#development = development;
this.#isLocalhost =
typeof development !== "undefined" ? development : isLocalhost;
this.#loadMaps = loadMaps;
this.#config = {};
this.#path = path;
Expand All @@ -107,7 +101,7 @@ export default class Eik {
/**
* Reads the Eik config from disk into the object instance, used for building {@link file} links in production.
*
* If {@link Options.loadMaps} is `true` the import maps
* If `loadMaps` is `true` the import maps
* defined in the Eik config will be fetched from the Eik server for
* use in {@link maps}.
*/
Expand Down Expand Up @@ -172,28 +166,27 @@ export default class Eik {

/**
* Similar to {@link file}, this method returns a path to the base on Eik
* (ex. https://eik.store.com/pkg/my-app/1.0.0), or {@link Options.base}
* if {@link Options.development} is true.
* (ex. https://eik.store.com/pkg/my-app/1.0.0), or `base` if `isLocalhost` is true.
*
* You can use this instead of `file` if you have a directory full of files
* and you don't need {@link Asset.integrity}.
*
* @returns {string} The base path for assets published on Eik
* @throws when {@link Options.development} is false if called before calling {@link load}
* @throws when `isLocalhost` is false if called before calling {@link load}
*/
base() {
if (this.#development) return this.#base;
if (this.#isLocalhost) return this.#base;
return `${this.server}${this.pathname}`;
}

/**
* Get a link to a file that is published on Eik when running in production.
* When {@link Options.development} is `true` the pathname is prefixed
* with the {@link Options.base} option instead of pointing to Eik.
* When `isLocalhost` is `true` the pathname is prefixed
* with the `base` option instead of pointing to Eik.
*
* @param {string} pathname pathname to the file relative to the base on Eik (ex: /path/to/script.js for a prod URL https://eik.store.com/pkg/my-app/1.0.0/path/to/script.js)
* @returns {import('./asset.js').Asset}
* @throws when {@link Options.development} is false if called before calling {@link load}
* @throws when `isLocalhost` is false if called before calling {@link load}
*
* @example
* ```js
Expand Down Expand Up @@ -239,13 +232,13 @@ export default class Eik {
}

/**
* When {@link Options.loadMaps} is `true` and you call {@link load}, the client
* When `loadMaps` is `true` and you call {@link load}, the client
* fetches the configured import maps from the Eik server.
*
* This method returns the import maps that were fetched during `load`.
*
* @returns {ImportMap[]}
* @throws if {@link Options.loadMaps} is not `true` or called before calling {@link load}
* @throws if `loadMaps` is not `true` or called before calling {@link load}
*
* @example
* ```js
Expand Down
43 changes: 43 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,49 @@ tap.test(
},
);

tap.test(
'Client - Default settings - Config is loaded and isLocalhost is set to "true"',
async (t) => {
const client = new Eik({
isLocalhost: true,
path: t.context.fixture,
});
await client.load();

t.equal(client.name, "eik-fixture", 'Should be same as "name" in eik.json');
t.equal(client.version, "1.0.2", 'Should be same as "version" in eik.json');
t.equal(client.type, "pkg", 'Should be "pkg" in eik.json');
t.equal(
client.server,
t.context.address,
'Should be same as "server" in eik.json',
);
t.equal(
client.pathname,
"/pkg/eik-fixture/1.0.2",
'Should be composed path based on "type", "name" and "version"',
);
t.end();
},
);

tap.test(
'Client - Retrieve a file path - isLocalhost is set to "false"',
async (t) => {
const client = new Eik({
path: t.context.fixture,
isLocalhost: false,
});
await client.load();

const file = "/some/path/foo.js";
const resolved = client.file(file);

t.equal(resolved.value, `${client.server}${client.pathname}${file}`);
t.end();
},
);

tap.test(
'Client - Retrieve a file path - Development mode is set to "true" - Base is unset',
async (t) => {
Expand Down
26 changes: 26 additions & 0 deletions types/options.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
export type Options = {
/**
* Base root to be used for returned asset files.
*/
base?: string;
/**
* Determines whether the client produces links to localhost (f. ex. during development) or to the Eik server.
* @default false
*/
isLocalhost?: boolean;
/**
* @default false
* @deprecated Prefer `isLocalhost` instead for clarity.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do a proper deprecation warning: https://nodejs.org/api/util.html#utildeprecatefn-msg-code-options

Copy link
Contributor Author

@wkillerud wkillerud Feb 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I looked into that, seems to only be for whole functions.

*/
development?: boolean;
/**
* Specifies whether import maps defined in the config should be loaded from the Eik server or not.
* @default false
*/
loadMaps?: boolean;
/**
* Path to directory containing an eik.json file or package.json with eik config.
* @default process.cwd()
*/
path?: string;
};