diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index b3998ab..f621dbd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -4,8 +4,6 @@ on: push: branches: - master - - alpha - - beta - next jobs: @@ -17,7 +15,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 16.x - name: npm install run: | npm install @@ -44,7 +42,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v3 with: - node-version: 14.x + node-version: 16.x - name: npm install run: | npm install diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 35d73ad..9c236af 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -8,7 +8,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, macOS-latest, windows-latest] - node-version: [14.x, 16.x] + node-version: [16.x, 18.x] steps: - uses: actions/checkout@v3 - name: Use Node.js ${{ matrix.node-version }} diff --git a/CHANGELOG.md b/CHANGELOG.md index fb1beca..eecb798 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,71 @@ -## [1.1.29](https://github.com/eik-lib/node-client/compare/v1.1.28...v1.1.29) (2022-08-15) +# [2.0.0-next.5](https://github.com/eik-lib/node-client/compare/v2.0.0-next.4...v2.0.0-next.5) (2022-09-23) + + +### Features + +* add .mapping(dep) shorthand method to resolve mapped bare imports directly ([a557cfd](https://github.com/eik-lib/node-client/commit/a557cfdc56f4553f721d1a67a7670eafc284b565)) + +# [2.0.0-next.4](https://github.com/eik-lib/node-client/compare/v2.0.0-next.3...v2.0.0-next.4) (2022-08-22) + + +### Features + +* Remove support for CJS. ESM only ([#106](https://github.com/eik-lib/node-client/issues/106)) ([d74f8c8](https://github.com/eik-lib/node-client/commit/d74f8c8266b67119d8d110524533a0bd7ce19e7d)) + + +### BREAKING CHANGES + +* This PR removes the support for CJS in this module. This module is now ESM only. + +* feat: Remove CJS support. ESM only. +* Support for CJS is now removed in this module. It is ESM only. + +* ci: use 0.0.0.0 instead of localhost + +* fix: remove console.log() statement + +Co-authored-by: Trygve Lie + +# [2.0.0-next.3](https://github.com/eik-lib/node-client/compare/v2.0.0-next.2...v2.0.0-next.3) (2022-08-18) ### Bug Fixes * **deps:** update dependency undici to v5.8.2 ([652c0af](https://github.com/eik-lib/node-client/commit/652c0af76d4eff970ba8954d8f287703c30acd73)) +# [2.0.0-next.2](https://github.com/eik-lib/node-client/compare/v2.0.0-next.1...v2.0.0-next.2) (2022-08-18) + + +### Features + +* Use the new @eik/common-config-loader module ([#104](https://github.com/eik-lib/node-client/issues/104)) ([5de927c](https://github.com/eik-lib/node-client/commit/5de927ca74c461be8d6bbd0048a2afc6812cb085)) + +# [2.0.0-next.1](https://github.com/eik-lib/node-client/compare/v1.1.28...v2.0.0-next.1) (2022-08-08) + + +### Bug Fixes + +* Add CommonJS support ([b634537](https://github.com/eik-lib/node-client/commit/b6345378236d1bf60dc1ff6ceee1a285ca335e7f)) +* Do not use getters and setters on public data object ([0505dcb](https://github.com/eik-lib/node-client/commit/0505dcb25b2563b826d5806fc30a7d148c111c00)) +* Make default value of integrity to be undefined ([a679f73](https://github.com/eik-lib/node-client/commit/a679f733351413e5e59cbd0f71c86fef8a08042c)) + + +### chore + +* Rename module to @eik/node-client ([f3d8c73](https://github.com/eik-lib/node-client/commit/f3d8c7325b90b345a79df731544f53ebb11c81bf)) + + +### Features + +* Make .file() return an object ([f53f15d](https://github.com/eik-lib/node-client/commit/f53f15dae288fda4b4527a3b4c69bab2e56f5169)) +* Rework module to suite current functionality of Eik ([559294c](https://github.com/eik-lib/node-client/commit/559294cc8d1bd793873ba02000da6376312e0160)) + + +### BREAKING CHANGES + +* Rename module to @eik/node-client +* API is reworked to suite the current functionality of Eik + ## [1.1.28](https://github.com/eik-lib/node-client/compare/v1.1.27...v1.1.28) (2022-08-08) diff --git a/README.md b/README.md index 1ee127e..ceb1047 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ Set the module in development mode or not. Whether import maps defined in the config should be loaded from the Eik server or not. The import maps is loaded by calling the `.load()` method and loaded the maps can be retrieved with the `.maps()` method. The import maps will be cached in the module. -## API +### options This module has the following API @@ -187,6 +187,37 @@ If `integrity` of the file is not available, the value for `integrity` will be ` Returns the import maps defined in Eik config from the Eik server. For the maps to be returned they need to be loaded from the Eik server. This is done by setting the `loadMaps` option on the constructor to `true`. +### .mapping(identifier) + +Returns the last mapping entry for a given bare import `identifier`. +`identifier` is a `string` key from an import map and the returned `string` is a the matching value from the same import map entry. + +#### arguments + +| option | default | type | required | details | +| ---------- | ------- | -------- | -------- | ------------------- | +| identifier | | `string` | `true` | Bare import map key | + +**Example:** + +If an import map being used looks like: + +```json +{ + "imports": { + "react": "https://myserver.com/react/18.0.0/react.min.js" + } +} +``` + +When the mapping method is called: + +```js +const absoluteURL = client.mapping('react'); +``` + +`absoluteURL` will be `https://myserver.com/react/18.0.0/react.min.js` + ## License Copyright (c) 2021 FINN.no diff --git a/package.json b/package.json index a0b6baf..b17cc5d 100644 --- a/package.json +++ b/package.json @@ -1,26 +1,19 @@ { "name": "@eik/node-client", - "version": "1.1.29", + "version": "2.0.0-next.5", "description": "A node.js client for interacting with a Eik server.", "type": "module", - "main": "./dist/index.cjs", - "exports": { - "import": "./src/index.js", - "require": "./dist/index.cjs" - }, + "main": "./src/index.js", "files": [ "CHANGELOG.md", "package.json", "LICENSE", - "dist", "src" ], "scripts": { "test": "tap --no-coverage", "lint:fix": "eslint --fix .", - "lint": "eslint .", - "prepare": "npm run -s build", - "build": "rollup -c" + "lint": "eslint ." }, "repository": { "type": "git", @@ -37,7 +30,7 @@ }, "homepage": "https://github.com/eik-lib/node-client#readme", "dependencies": { - "@eik/common": "3.0.1", + "@eik/common-config-loader": "4.0.0-next.8", "abslog": "2.4.0", "undici": "5.8.2" }, @@ -50,7 +43,6 @@ "eslint-plugin-import": "2.26.0", "eslint-plugin-prettier": "4.2.1", "prettier": "2.7.1", - "rollup": "2.77.2", "semantic-release": "19.0.3", "tap": "16.3.0", "@babel/eslint-parser": "7.18.9" diff --git a/release.config.cjs b/release.config.cjs index f195d37..1554435 100644 --- a/release.config.cjs +++ b/release.config.cjs @@ -20,8 +20,6 @@ module.exports = { preset: 'angular', branches: [ { name: 'master' }, - { name: 'alpha', prerelease: true }, - { name: 'beta', prerelease: true }, { name: 'next', prerelease: true }, ], }; diff --git a/rollup.config.js b/rollup.config.js deleted file mode 100644 index 75b9b92..0000000 --- a/rollup.config.js +++ /dev/null @@ -1,16 +0,0 @@ -export default { - input: 'src/index.js', - external: [ - '@eik/common', - 'undici', - 'abslog', - 'path', - ], - output: [ - { - exports: 'auto', - format: 'cjs', - file: 'dist/index.cjs', - }, - ], -}; diff --git a/src/index.js b/src/index.js index a38ef2c..5e964c9 100644 --- a/src/index.js +++ b/src/index.js @@ -1,21 +1,24 @@ -import { helpers } from '@eik/common'; +/* eslint-disable no-restricted-syntax */ import { request } from 'undici'; -import { join } from 'path'; +import { join } from 'node:path'; +import { URL } from 'node:url'; +import loader from '@eik/common-config-loader'; import Asset from './asset.js'; const trimSlash = (value = '') => { if (value.endsWith('/')) return value.substring(0, value.length - 1); return value; -} +}; + +const ABSOLUTE_URL_REGEX = /^[a-zA-Z][a-zA-Z\d+\-.]*?:/; const fetchImportMaps = async (urls = []) => { - try{ + try { const maps = urls.map(async (map) => { - const { - statusCode, - body - } = await request(map, { maxRedirections: 2 }); - + const { statusCode, body } = await request(map, { + maxRedirections: 2, + }); + if (statusCode === 404) { throw new Error('Import map could not be found on server'); } else if (statusCode >= 400 && statusCode < 500) { @@ -31,7 +34,7 @@ const fetchImportMaps = async (urls = []) => { `Unable to load import map file from server: ${err.message}`, ); } -} +}; export default class NodeClient { #development; @@ -55,7 +58,7 @@ export default class NodeClient { } async load() { - this.#config = await helpers.getDefaults(this.#path); + this.#config = await loader.getDefaults(this.#path); if (this.#loadMaps) { this.#maps = await fetchImportMaps(this.#config.map); } @@ -83,7 +86,8 @@ export default class NodeClient { } get pathname() { - if (this.#config.type && this.#config.name && this.#config.version) return join('/', this.type, this.name, this.version); + if (this.#config.type && this.#config.name && this.#config.version) + return join('/', this.type, this.name, this.version); throw new Error('Eik config was not loaded before calling .pathname'); } @@ -94,13 +98,32 @@ export default class NodeClient { file(file = '') { const base = this.base(); + let value; + if (base && ABSOLUTE_URL_REGEX.test(base)) { + const baseURL = new URL(base); + const subPath = join(baseURL.pathname, file); + value = new URL(subPath, base).toString(); + } else { + value = join(base, '/', file); + } + return new Asset({ - value: `${base}${file}`, + value }); } maps() { if (this.#config.version && this.#loadMaps) return this.#maps; - throw new Error('Eik config was not loaded or "loadMaps" is "false" when calling .maps()'); + throw new Error( + 'Eik config was not loaded or "loadMaps" is "false" when calling .maps()', + ); + } + + mapping(dependency) { + let mapping = null; + for (const map of this.maps()) { + if (map?.imports[dependency]) mapping = map.imports[dependency]; + } + return mapping; } } diff --git a/test/index.js b/test/index.js index e206460..fa1a82a 100644 --- a/test/index.js +++ b/test/index.js @@ -1,5 +1,5 @@ import { mkdtemp, writeFile } from 'fs/promises'; -import { helpers } from '@eik/common'; +import loader from '@eik/common-config-loader'; import path from 'path'; import http from 'http'; import tap from 'tap'; @@ -8,7 +8,7 @@ import os from 'os'; import NodeClient from '../src/index.js'; const FIXTURE_PATH = `${process.cwd()}/fixtures`; -const FIXTURE_FILE = await helpers.getDefaults(FIXTURE_PATH); +const FIXTURE_FILE = await loader.getDefaults(FIXTURE_PATH); const writeTempConfig = async (address) => { const pathname = await mkdtemp(path.join(os.tmpdir(), `eik-${address.port.toString()}-`)); @@ -47,7 +47,7 @@ class Server { listen() { return new Promise((resolve) => { - const connection = this.server.listen(0, 'localhost', () => { + const connection = this.server.listen(0, '0.0.0.0', () => { resolve(connection); }); }); @@ -175,17 +175,58 @@ tap.test('Client - Retrieve a file path - Development mode is set to "true" - Ba tap.test('Client - Retrieve a file path - Development mode is set to "true" - Base is set to absolute URL', async (t) => { const client = new NodeClient({ development: true, - base: 'http://localhost:7777/prefix/', + base: 'http://0.0.0.0:7777/prefix/', path: t.context.fixture, }); await client.load(); const resolved = client.file('/some/path/foo.js'); + t.equal(resolved.value, 'http://0.0.0.0:7777/prefix/some/path/foo.js'); + t.end(); +}); + +tap.test('Client - Retrieve a file path - Development mode is set to "true" - Base is set to absolute URL - file without starting slash', async (t) => { + const client = new NodeClient({ + development: true, + base: 'http://localhost:7777/prefix/', + path: t.context.fixture, + }); + await client.load(); + + const resolved = client.file('some/path/foo.js'); + t.equal(resolved.value, 'http://localhost:7777/prefix/some/path/foo.js'); t.end(); }); +tap.test('Client - Retrieve a file path - Development mode is set to "true" - Base is set to relative path - file without starting slash', async (t) => { + const client = new NodeClient({ + development: true, + base: '/prefix/', + path: t.context.fixture, + }); + await client.load(); + + const resolved = client.file('some/path/foo.js'); + + t.equal(resolved.value, '/prefix/some/path/foo.js'); + t.end(); +}); + +tap.test('Client - Retrieve a file path - Development mode is set to "true" - Base is unset - file without starting slash', async (t) => { + const client = new NodeClient({ + development: true, + path: t.context.fixture, + }); + await client.load(); + + const resolved = client.file('some/path/foo.js'); + + t.equal(resolved.value, '/some/path/foo.js'); + t.end(); +}); + tap.test('Client - Load maps', async (t) => { const client = new NodeClient({ loadMaps: true, @@ -194,6 +235,7 @@ tap.test('Client - Load maps', async (t) => { await client.load(); const maps = client.maps(); + t.same(maps, [ { imports: { eik: '/src/eik.js' } }, { imports: { eik: '/src/eik.js' } } @@ -232,14 +274,14 @@ tap.test('Client - Retrieve a base - Development mode is set to "true" - Base is tap.test('Client - Retrieve a base - Development mode is set to "true" - Base is set to a absolute URL', async (t) => { const client = new NodeClient({ development: true, - base: 'http://localhost:7777/prefix/some/path/', + base: 'http://0.0.0.0:7777/prefix/some/path/', path: t.context.fixture, }); await client.load(); const resolved = client.base(); - t.equal(resolved, 'http://localhost:7777/prefix/some/path'); + t.equal(resolved, 'http://0.0.0.0:7777/prefix/some/path'); t.end(); }); @@ -254,3 +296,16 @@ tap.test('Client - Retrieve a base - Development mode is set to "false"', async t.equal(resolved, `${t.context.address}/pkg/eik-fixture/1.0.2`); t.end(); }); + +tap.test('Client - Resolve a mapping', async (t) => { + const client = new NodeClient({ + path: t.context.fixture, + loadMaps: true, + }); + await client.load(); + + const mapping = client.mapping('eik'); + + t.equal(mapping, '/src/eik.js'); + t.end(); +});