@shgysk8zer0/importmap 1.2.4 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -6,7 +6,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
- ## [v1.2.4] - 2023--09-07
9
+ ## [v1.3.0] - 2023-10-31
10
+
11
+ ### Added
12
+ - Auto-update from `unpkg.com` (no Firebase updates) by running `update.js`
13
+
14
+ ### Changed
15
+ - Importmap is now stored in `importmap.json`
16
+ - Update `exports`, etc.
17
+
18
+ ### Removed
19
+ - No more `versions.js` - It is directly in the JSON
20
+
21
+ ## [v1.2.5] - 2023-09-08
22
+
23
+ ### Fixed
24
+ - Fix typo in mapping for `@shgysk8zer0/jss`
25
+
26
+ ## [v1.2.4] - 2023-09-07
10
27
 
11
28
  ### Changed
12
29
  - Update `@shgysk8zer0/components`
package/cli.mjs CHANGED
@@ -5,7 +5,8 @@ import { readJSONFile, writeJSONFile } from '@shgysk8zer0/npm-utils/json';
5
5
  import { readYAMLFile, writeYAMLFile } from '@shgysk8zer0/npm-utils/yaml';
6
6
  import { program } from 'commander';
7
7
  import { extname } from 'node:path';
8
- import { importmap } from './index.js';
8
+ import { importmap } from './index.mjs';
9
+ import { updateImportMap } from './html.js';
9
10
 
10
11
  function guessFileType(file) {
11
12
  const ext = extname(file).toLowerCase();
@@ -18,6 +19,9 @@ function guessFileType(file) {
18
19
  case '.json':
19
20
  return 'json';
20
21
 
22
+ case '.html':
23
+ return 'html';
24
+
21
25
  default:
22
26
  throw new TypeError(`"${ext}" is not a supported file extension for file ${file}.`);
23
27
  }
@@ -35,7 +39,7 @@ async function parse(file, { encoding, signal } = {}) {
35
39
  }
36
40
 
37
41
  async function init() {
38
- const { version: VERSION } = await readJSONFile(new URL('./package.json', import.meta.url).pathname);
42
+ const { version: VERSION } = await readJSONFile(new URL('./package.json', import.meta.url));
39
43
 
40
44
  program
41
45
  .name('importmap-utils')
@@ -54,7 +58,6 @@ async function init() {
54
58
  }
55
59
 
56
60
  init().then(async ({ opts: { input, encoding, format, output }}) => {
57
- console.log({ input, encoding, format, output });
58
61
  const mod = typeof input === 'string'
59
62
  ? await parse(input, { encoding }).then(({ imports, scope = {}, ...rest }) => ({
60
63
  ...rest,
@@ -73,5 +76,9 @@ init().then(async ({ opts: { input, encoding, format, output }}) => {
73
76
  case 'yaml':
74
77
  await writeYAMLFile(output, mod, { encoding });
75
78
  break;
79
+
80
+ case 'html':
81
+ await updateImportMap(output, { spaces: null });
82
+ break;
76
83
  }
77
84
  });
package/importmap.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "imports": {
3
+ "@shgysk8zer0/kazoo/": "https://unpkg.com/@shgysk8zer0/kazoo@0.2.5/",
4
+ "@shgysk8zer0/konami": "https://unpkg.com/@shgysk8zer0/konami@1.1.1/konami.js",
5
+ "@shgysk8zer0/polyfills": "https://unpkg.com/@shgysk8zer0/polyfills@0.2.6/all.min.js",
6
+ "@shgysk8zer0/polyfills/": "https://unpkg.com/@shgysk8zer0/polyfills@0.2.6/",
7
+ "@shgysk8zer0/jswaggersheets": "https://unpkg.com/@shgysk8zer0/jswaggersheets@1.1.0/swagger.js",
8
+ "@shgysk8zer0/jswaggersheets/": "https://unpkg.com/@shgysk8zer0/jswaggersheets@1.1.0/",
9
+ "@shgysk8zer0/jss/": "https://unpkg.com/@shgysk8zer0/jss@1.0.1/",
10
+ "@shgysk8zer0/consts/": "https://unpkg.com/@shgysk8zer0/consts@1.0.7/",
11
+ "@shgysk8zer0/http/": "https://unpkg.com/@shgysk8zer0/http@1.0.5/",
12
+ "@shgysk8zer0/http-status": "https://unpkg.com/@shgysk8zer0/http-status@1.1.1/http-status.js",
13
+ "@shgysk8zer0/components/": "https://unpkg.com/@shgysk8zer0/components@0.1.5/",
14
+ "@kernvalley/components/": "https://unpkg.com/@kernvalley/components@1.1.0/",
15
+ "@webcomponents/custom-elements": "https://unpkg.com/@webcomponents/custom-elements@1.6.0/custom-elements.min.js",
16
+ "leaflet": "https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js",
17
+ "urlpattern-polyfill": "https://unpkg.com/urlpattern-polyfill@9.0.0/index.js",
18
+ "highlight.js": "https://unpkg.com/@highlightjs/cdn-assets@11.9.0/es/highlight.min.js",
19
+ "highlight.js/": "https://unpkg.com/@highlightjs/cdn-assets@11.9.0/",
20
+ "marked": "https://unpkg.com/marked@9.1.4/lib/marked.esm.js",
21
+ "marked-highlight": "https://unpkg.com/marked-highlight@2.0.6/src/index.js",
22
+ "firebase/": "https://www.gstatic.com/firebasejs/9.23.0/"
23
+ },
24
+ "scope": {}
25
+ }
package/index.cjs CHANGED
@@ -2,48 +2,147 @@
2
2
 
3
3
  var promises = require('node:fs/promises');
4
4
  var node_crypto = require('node:crypto');
5
+ var yaml_js = require('@shgysk8zer0/npm-utils/yaml.js');
6
+ var json_js = require('@shgysk8zer0/npm-utils/json.js');
5
7
 
6
- const versions = {
7
- '@shgysk8zer0/kazoo': '0.2.3',
8
- '@shgysk8zer0/konami': '1.1.0',
9
- '@shgysk8zer0/polyfills': '0.2.4',
10
- '@shgysk8zer0/components': '0.1.3',
11
- '@shgysk8zer0/http-status': '1.1.1',
12
- '@shgysk8zer0/jswaggersheets': '1.1.0',
13
- '@shgysk8zer0/jss': '1.0.1',
14
- '@kernvalley/components': '1.1.0',
15
- '@webcomponents/custom-elements': '1.6.0',
16
- 'leaflet': '1.9.4',
17
- 'firebase': '9.23.0',
18
- 'urlpattern-polyfill': '9.0.0',
19
- 'highlight.js': '11.8.0',
20
- 'marked': '5.1.0',
21
- 'marked-highlight': '2.0.1',
8
+ const imports$1 = {
9
+ "@shgysk8zer0/kazoo/": "https://unpkg.com/@shgysk8zer0/kazoo@0.2.5/",
10
+ "@shgysk8zer0/konami": "https://unpkg.com/@shgysk8zer0/konami@1.1.1/konami.js",
11
+ "@shgysk8zer0/polyfills": "https://unpkg.com/@shgysk8zer0/polyfills@0.2.6/all.min.js",
12
+ "@shgysk8zer0/polyfills/": "https://unpkg.com/@shgysk8zer0/polyfills@0.2.6/",
13
+ "@shgysk8zer0/jswaggersheets": "https://unpkg.com/@shgysk8zer0/jswaggersheets@1.1.0/swagger.js",
14
+ "@shgysk8zer0/jswaggersheets/": "https://unpkg.com/@shgysk8zer0/jswaggersheets@1.1.0/",
15
+ "@shgysk8zer0/jss/": "https://unpkg.com/@shgysk8zer0/jss@1.0.1/",
16
+ "@shgysk8zer0/consts/": "https://unpkg.com/@shgysk8zer0/consts@1.0.7/",
17
+ "@shgysk8zer0/http/": "https://unpkg.com/@shgysk8zer0/http@1.0.5/",
18
+ "@shgysk8zer0/http-status": "https://unpkg.com/@shgysk8zer0/http-status@1.1.1/http-status.js",
19
+ "@shgysk8zer0/components/": "https://unpkg.com/@shgysk8zer0/components@0.1.5/",
20
+ "@kernvalley/components/": "https://unpkg.com/@kernvalley/components@1.1.0/",
21
+ "@webcomponents/custom-elements": "https://unpkg.com/@webcomponents/custom-elements@1.6.0/custom-elements.min.js",
22
+ leaflet: "https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js",
23
+ "urlpattern-polyfill": "https://unpkg.com/urlpattern-polyfill@9.0.0/index.js",
24
+ "highlight.js": "https://unpkg.com/@highlightjs/cdn-assets@11.9.0/es/highlight.min.js",
25
+ "highlight.js/": "https://unpkg.com/@highlightjs/cdn-assets@11.9.0/",
26
+ marked: "https://unpkg.com/marked@9.1.4/lib/marked.esm.js",
27
+ "marked-highlight": "https://unpkg.com/marked-highlight@2.0.6/src/index.js",
28
+ "firebase/": "https://www.gstatic.com/firebasejs/9.23.0/"
22
29
  };
23
-
24
- const imports = {
25
- '@shgysk8zer0/kazoo/': `https://unpkg.com/@shgysk8zer0/kazoo@${versions['@shgysk8zer0/kazoo']}/`,
26
- '@shgysk8zer0/konami': `https://unpkg.com/@shgysk8zer0/konami@${versions['@shgysk8zer0/konami']}/konami.js`,
27
- '@shgysk8zer0/polyfills': `https://unpkg.com/@shgysk8zer0/polyfills@${versions['@shgysk8zer0/polyfills']}/all.min.js`,
28
- '@shgysk8zer0/polyfills/': `https://unpkg.com/@shgysk8zer0/polyfills@${versions['@shgysk8zer0/polyfills']}/`,
29
- '@shgysk8zer0/jswaggersheets': `https://unpkg.com/@shgysk8zer0/jswaggersheets@${versions['@shgysk8zer0/jswaggersheets']}/swagger.js`,
30
- '@shgysk8zer0/jswaggersheets/': `https://unpkg.com/@shgysk8zer0/jswaggersheets@${versions['@shgysk8zer0/jswaggersheets']}/`,
31
- '@shgysk8zer0/jss/': `https://unpkg.com/@shgysk8zer0/jss@${versions['@shgysk8zer0/jss/']}/`,
32
- '@shgysk8zer0/http-status': `https://unpkg.com/@shgysk8zer0/http-status@${versions['@shgysk8zer0/http-status']}/http-status.js`,
33
- '@shgysk8zer0/components/': `https://unpkg.com/@shgysk8zer0/components@${versions['@shgysk8zer0/components']}/`,
34
- '@kernvalley/components/': `https://unpkg.com/@kernvalley/components@${versions['@kernvalley/components']}/`,
35
- '@webcomponents/custom-elements': `https://unpkg.com/@webcomponents/custom-elements@${versions['@webcomponents/custom-elements']}/custom-elements.min.js`,
36
- 'leaflet': `https://unpkg.com/leaflet@${versions.leaflet}/dist/leaflet-src.esm.js`,
37
- 'firebase/': `https://www.gstatic.com/firebasejs/${versions.firebase}/`,
38
- 'urlpattern-polyfill': `https://unpkg.com/urlpattern-polyfill@${versions['urlpattern-polyfill']}/index.js`,
39
- 'highlight.js': `https://unpkg.com/@highlightjs/cdn-assets@${versions['highlight.js']}/es/highlight.min.js`,
40
- 'highlight.js/': `https://unpkg.com/@highlightjs/cdn-assets@${versions['highlight.js']}/`,
41
- 'marked': `https://unpkg.com/marked@${versions.marked}/src/marked.js`,
42
- 'marked-highlight': `https://unpkg.com/marked-highlight@${versions['marked-highlight']}/src/index.js`
30
+ const scope$1 = {
31
+ };
32
+ var importmap = {
33
+ imports: imports$1,
34
+ scope: scope$1
43
35
  };
44
36
 
45
- const scope = {};
46
- const importmap = { imports, scope };
37
+ const UNPKG = 'https://unpkg.com/';
38
+
39
+ const cache = new Map();
40
+
41
+ function parseUnpkgURL(src) {
42
+ const url = new URL(src, UNPKG);
43
+
44
+ if (! url.hostname === UNPKG || url.pathname.length === 1 || url.pathname === '/[object%20Object]') {
45
+ throw new Error(`${src} is not an unpkg URL.`);
46
+ } else {
47
+ const path = url.pathname.substr(1).split('/');
48
+
49
+ if (path.length === 0) {
50
+ throw new Error(`Invalid unpkg URL: ${src}`);
51
+ } else if (path.length !== 1 && path[0].startsWith('@')) {
52
+ const [pkg, version = null] = path[1].split('@');
53
+ return { scope: path[0], pkg, version, module: path.splice(2).join('/') };
54
+ } else {
55
+ const [pkg, version = null] = path[0].split('@');
56
+ return { scope: null, pkg, version, module: path.splice(1).join('/') };
57
+ }
58
+ }
59
+ }
60
+
61
+ function getUnpkgURL({ scope, pkg, version, module = '' }) {
62
+ // console.log({ scope, pkg, version });
63
+ if (typeof pkg !== 'string' || pkg.length === 0) {
64
+ throw new TypeError('Package name must be a non-empty string.');
65
+ } else if (typeof version !== 'string' || version.length === 0) {
66
+ throw new TypeError('Version must be a non-empty string.');
67
+ } else if (typeof scope === 'string' && scope.length !== 0) {
68
+ return new URL(`/${scope}/${pkg}@${version}/${module}`, UNPKG).href;
69
+ } else {
70
+ return new URL(`/${pkg}@${version}/${module}`, UNPKG).href;
71
+ }
72
+ }
73
+
74
+ async function getLatestVersion({ scope, pkg, signal } = {}) {
75
+ const path = typeof scope === 'string' ? `/${scope}/${pkg}/` : `/${pkg}/`;
76
+
77
+ if (cache.has(path)) {
78
+ return await cache.get(path);
79
+ } else {
80
+ const url = new URL(path, 'https://unpkg.com/');
81
+ url.searchParams.set('meta', '');
82
+
83
+ const promise = fetch(url, { method: 'HEAD', signal }).then(resp => {
84
+ const { version } = parseUnpkgURL(resp.url);
85
+ return version;
86
+ });
87
+
88
+ cache.set(path, promise);
89
+ return promise;
90
+ }
91
+ }
92
+
93
+ async function update(imports) {
94
+ let updated = false;
95
+
96
+ const entries = await Promise.all(Object.entries(imports)
97
+ .filter(([,val]) => val.startsWith(UNPKG))
98
+ .map(async ([key, val]) => {
99
+ const { scope, pkg, version: oldVersion, module } = parseUnpkgURL(val);
100
+ const version = await getLatestVersion({ scope, pkg });
101
+
102
+ if (! updated && version > oldVersion) {
103
+ updated = true;
104
+ }
105
+
106
+ return [key, getUnpkgURL({ scope, pkg, version, module })];
107
+ })
108
+ );
109
+
110
+ return { imports: Object.fromEntries(entries), updated };
111
+ }
112
+
113
+ async function updateYAML(file) {
114
+ const importmap = await yaml_js.readYAMLFile(file);
115
+ const { updated, imports } = await update(importmap.imports);
116
+
117
+ if (updated) {
118
+ await yaml_js.writeYAMLFile(file, { ...importmap, imports: { ...importmap.imports, ...imports }});
119
+ return true;
120
+ } else {
121
+ return false;
122
+ }
123
+ }
124
+
125
+ async function updateJSON(file) {
126
+ const importmap = await json_js.readJSONFile(file);
127
+ const { updated, imports } = await update(importmap.imports);
128
+
129
+ if (updated) {
130
+ await json_js.writeJSONFile(file, { ...importmap, imports: { ...importmap.imports, ...imports }});
131
+ return true;
132
+ } else {
133
+ return false;
134
+ }
135
+ }
136
+
137
+ var unpkg = /*#__PURE__*/Object.freeze({
138
+ __proto__: null,
139
+ update: update,
140
+ updateJSON: updateJSON,
141
+ updateYAML: updateYAML
142
+ });
143
+
144
+ const { imports, scope } = importmap;
145
+
47
146
  const ENCODING = 'utf8';
48
147
  const ALGO = 'sha384';
49
148
 
@@ -76,12 +175,10 @@ function getImportmapIntegrity({
76
175
  function getImportMapScript({
77
176
  importmap = { imports, scope },
78
177
  algo = ALGO,
79
- encoding = ENCODING,
80
178
  spaces = 2,
81
179
  } = {}) {
82
- const integrity = getImportmapIntegrity({ importmap, algo, encoding, spaces });
83
- const json = JSON.stringify(importmap, null, spaces);
84
- return `<script type="importmap" integrity="${integrity}">${json}</script>`;
180
+ const integrity = getImportmapIntegrity({ importmap, algo, spaces });
181
+ return `<script type="importmap" integrity="${integrity}">${JSON.stringify(importmap, null, spaces)}</script>`;
85
182
  }
86
183
 
87
184
  exports.ALGO = ALGO;
@@ -93,3 +190,4 @@ exports.importmap = importmap;
93
190
  exports.imports = imports;
94
191
  exports.mergeWithImportmap = mergeWithImportmap;
95
192
  exports.scope = scope;
193
+ exports.unpkg = unpkg;
package/index.mjs ADDED
@@ -0,0 +1,182 @@
1
+ import { writeFile } from 'node:fs/promises';
2
+ import { createHash } from 'node:crypto';
3
+ import { readYAMLFile, writeYAMLFile } from '@shgysk8zer0/npm-utils/yaml.js';
4
+ import { readJSONFile, writeJSONFile } from '@shgysk8zer0/npm-utils/json.js';
5
+
6
+ const imports$1 = {
7
+ "@shgysk8zer0/kazoo/": "https://unpkg.com/@shgysk8zer0/kazoo@0.2.5/",
8
+ "@shgysk8zer0/konami": "https://unpkg.com/@shgysk8zer0/konami@1.1.1/konami.js",
9
+ "@shgysk8zer0/polyfills": "https://unpkg.com/@shgysk8zer0/polyfills@0.2.6/all.min.js",
10
+ "@shgysk8zer0/polyfills/": "https://unpkg.com/@shgysk8zer0/polyfills@0.2.6/",
11
+ "@shgysk8zer0/jswaggersheets": "https://unpkg.com/@shgysk8zer0/jswaggersheets@1.1.0/swagger.js",
12
+ "@shgysk8zer0/jswaggersheets/": "https://unpkg.com/@shgysk8zer0/jswaggersheets@1.1.0/",
13
+ "@shgysk8zer0/jss/": "https://unpkg.com/@shgysk8zer0/jss@1.0.1/",
14
+ "@shgysk8zer0/consts/": "https://unpkg.com/@shgysk8zer0/consts@1.0.7/",
15
+ "@shgysk8zer0/http/": "https://unpkg.com/@shgysk8zer0/http@1.0.5/",
16
+ "@shgysk8zer0/http-status": "https://unpkg.com/@shgysk8zer0/http-status@1.1.1/http-status.js",
17
+ "@shgysk8zer0/components/": "https://unpkg.com/@shgysk8zer0/components@0.1.5/",
18
+ "@kernvalley/components/": "https://unpkg.com/@kernvalley/components@1.1.0/",
19
+ "@webcomponents/custom-elements": "https://unpkg.com/@webcomponents/custom-elements@1.6.0/custom-elements.min.js",
20
+ leaflet: "https://unpkg.com/leaflet@1.9.4/dist/leaflet-src.esm.js",
21
+ "urlpattern-polyfill": "https://unpkg.com/urlpattern-polyfill@9.0.0/index.js",
22
+ "highlight.js": "https://unpkg.com/@highlightjs/cdn-assets@11.9.0/es/highlight.min.js",
23
+ "highlight.js/": "https://unpkg.com/@highlightjs/cdn-assets@11.9.0/",
24
+ marked: "https://unpkg.com/marked@9.1.4/lib/marked.esm.js",
25
+ "marked-highlight": "https://unpkg.com/marked-highlight@2.0.6/src/index.js",
26
+ "firebase/": "https://www.gstatic.com/firebasejs/9.23.0/"
27
+ };
28
+ const scope$1 = {
29
+ };
30
+ var importmap = {
31
+ imports: imports$1,
32
+ scope: scope$1
33
+ };
34
+
35
+ const UNPKG = 'https://unpkg.com/';
36
+
37
+ const cache = new Map();
38
+
39
+ function parseUnpkgURL(src) {
40
+ const url = new URL(src, UNPKG);
41
+
42
+ if (! url.hostname === UNPKG || url.pathname.length === 1 || url.pathname === '/[object%20Object]') {
43
+ throw new Error(`${src} is not an unpkg URL.`);
44
+ } else {
45
+ const path = url.pathname.substr(1).split('/');
46
+
47
+ if (path.length === 0) {
48
+ throw new Error(`Invalid unpkg URL: ${src}`);
49
+ } else if (path.length !== 1 && path[0].startsWith('@')) {
50
+ const [pkg, version = null] = path[1].split('@');
51
+ return { scope: path[0], pkg, version, module: path.splice(2).join('/') };
52
+ } else {
53
+ const [pkg, version = null] = path[0].split('@');
54
+ return { scope: null, pkg, version, module: path.splice(1).join('/') };
55
+ }
56
+ }
57
+ }
58
+
59
+ function getUnpkgURL({ scope, pkg, version, module = '' }) {
60
+ // console.log({ scope, pkg, version });
61
+ if (typeof pkg !== 'string' || pkg.length === 0) {
62
+ throw new TypeError('Package name must be a non-empty string.');
63
+ } else if (typeof version !== 'string' || version.length === 0) {
64
+ throw new TypeError('Version must be a non-empty string.');
65
+ } else if (typeof scope === 'string' && scope.length !== 0) {
66
+ return new URL(`/${scope}/${pkg}@${version}/${module}`, UNPKG).href;
67
+ } else {
68
+ return new URL(`/${pkg}@${version}/${module}`, UNPKG).href;
69
+ }
70
+ }
71
+
72
+ async function getLatestVersion({ scope, pkg, signal } = {}) {
73
+ const path = typeof scope === 'string' ? `/${scope}/${pkg}/` : `/${pkg}/`;
74
+
75
+ if (cache.has(path)) {
76
+ return await cache.get(path);
77
+ } else {
78
+ const url = new URL(path, 'https://unpkg.com/');
79
+ url.searchParams.set('meta', '');
80
+
81
+ const promise = fetch(url, { method: 'HEAD', signal }).then(resp => {
82
+ const { version } = parseUnpkgURL(resp.url);
83
+ return version;
84
+ });
85
+
86
+ cache.set(path, promise);
87
+ return promise;
88
+ }
89
+ }
90
+
91
+ async function update(imports) {
92
+ let updated = false;
93
+
94
+ const entries = await Promise.all(Object.entries(imports)
95
+ .filter(([,val]) => val.startsWith(UNPKG))
96
+ .map(async ([key, val]) => {
97
+ const { scope, pkg, version: oldVersion, module } = parseUnpkgURL(val);
98
+ const version = await getLatestVersion({ scope, pkg });
99
+
100
+ if (! updated && version > oldVersion) {
101
+ updated = true;
102
+ }
103
+
104
+ return [key, getUnpkgURL({ scope, pkg, version, module })];
105
+ })
106
+ );
107
+
108
+ return { imports: Object.fromEntries(entries), updated };
109
+ }
110
+
111
+ async function updateYAML(file) {
112
+ const importmap = await readYAMLFile(file);
113
+ const { updated, imports } = await update(importmap.imports);
114
+
115
+ if (updated) {
116
+ await writeYAMLFile(file, { ...importmap, imports: { ...importmap.imports, ...imports }});
117
+ return true;
118
+ } else {
119
+ return false;
120
+ }
121
+ }
122
+
123
+ async function updateJSON(file) {
124
+ const importmap = await readJSONFile(file);
125
+ const { updated, imports } = await update(importmap.imports);
126
+
127
+ if (updated) {
128
+ await writeJSONFile(file, { ...importmap, imports: { ...importmap.imports, ...imports }});
129
+ return true;
130
+ } else {
131
+ return false;
132
+ }
133
+ }
134
+
135
+ var unpkg = /*#__PURE__*/Object.freeze({
136
+ __proto__: null,
137
+ update: update,
138
+ updateJSON: updateJSON,
139
+ updateYAML: updateYAML
140
+ });
141
+
142
+ const { imports, scope } = importmap;
143
+
144
+ const ENCODING = 'utf8';
145
+ const ALGO = 'sha384';
146
+
147
+ function mergeWithImportmap({ imports = {}, scope = {}}) {
148
+ return {
149
+ imports: { ...importmap.imports, ...imports },
150
+ scope: { ...importmap.scope, ...scope },
151
+ };
152
+ }
153
+
154
+ async function createImportmapJSON(path = 'importmap.json', {
155
+ importmap = { imports, scope },
156
+ spaces = 2,
157
+ signal,
158
+ } = {}) {
159
+ await writeFile(path, JSON.stringify(importmap, null, spaces), { encoding: ENCODING, signal });
160
+ }
161
+
162
+ function getImportmapIntegrity({
163
+ importmap = { imports, scope },
164
+ algo = ALGO,
165
+ encoding = ENCODING,
166
+ spaces = 2,
167
+ } = {}) {
168
+ const hash = createHash(algo);
169
+ hash.update(JSON.stringify(importmap, null, spaces), encoding);
170
+ return `${algo}-${hash.digest('base64')}`;
171
+ }
172
+
173
+ function getImportMapScript({
174
+ importmap = { imports, scope },
175
+ algo = ALGO,
176
+ spaces = 2,
177
+ } = {}) {
178
+ const integrity = getImportmapIntegrity({ importmap, algo, spaces });
179
+ return `<script type="importmap" integrity="${integrity}">${JSON.stringify(importmap, null, spaces)}</script>`;
180
+ }
181
+
182
+ export { ALGO, ENCODING, createImportmapJSON, getImportMapScript, getImportmapIntegrity, importmap, imports, mergeWithImportmap, scope, unpkg };
package/package.json CHANGED
@@ -1,21 +1,31 @@
1
1
  {
2
2
  "name": "@shgysk8zer0/importmap",
3
- "version": "1.2.4",
3
+ "version": "1.3.0",
4
4
  "engines": {
5
5
  "node": ">=18.0.0"
6
6
  },
7
7
  "description": "Front-End dependencies based on `<script type=\"importmap\">`",
8
8
  "type": "module",
9
- "module": "./index.js",
9
+ "module": "./index.mjs",
10
10
  "main": "./index.cjs",
11
- "unpkg": "./index.js",
11
+ "unpkg": "./index.mjs",
12
12
  "exports": {
13
13
  ".": {
14
- "import": "./index.js",
14
+ "import": "./index.mjs",
15
15
  "require": "./index.cjs"
16
16
  },
17
+ "./*.js": {
18
+ "import": "./*.mjs",
19
+ "require": "./*.cjs"
20
+ },
21
+ "./*.mjs": {
22
+ "import": "./*.mjs"
23
+ },
24
+ "./*.cjs": {
25
+ "require": "./*.cjs"
26
+ },
17
27
  "./*": {
18
- "import": "./*.js",
28
+ "import": "./*.mjs",
19
29
  "require": "./*.cjs"
20
30
  }
21
31
  },
@@ -27,7 +37,7 @@
27
37
  "preversion": "npm test",
28
38
  "prepare": "npm run build",
29
39
  "lint:js": "eslint .",
30
- "fix:js": "eslint. --fix",
40
+ "fix:js": "eslint . --fix",
31
41
  "build": "npm run build:js",
32
42
  "build:js": "rollup -c",
33
43
  "test:imports": "rollup -c rollup.test.config.js",
@@ -48,11 +58,15 @@
48
58
  },
49
59
  "homepage": "https://github.com/shgysk8zer0/importmap#readme",
50
60
  "devDependencies": {
61
+ "@babel/eslint-parser": "^7.22.15",
62
+ "@babel/eslint-plugin": "^7.22.10",
63
+ "@babel/plugin-syntax-import-assertions": "^7.22.5",
64
+ "@rollup/plugin-json": "^6.0.1",
51
65
  "@shgysk8zer0/js-utils": "^1.0.1",
52
- "@shgysk8zer0/rollup-import": "^1.2.0"
66
+ "@shgysk8zer0/rollup-import": "^1.2.2"
53
67
  },
54
68
  "dependencies": {
55
- "@shgysk8zer0/npm-utils": "^1.1.0",
56
- "commander": "^11.0.0"
69
+ "@shgysk8zer0/npm-utils": "^1.1.2",
70
+ "commander": "^11.1.0"
57
71
  }
58
72
  }
package/unpkg.js ADDED
@@ -0,0 +1,47 @@
1
+ import { readYAMLFile, writeYAMLFile } from '@shgysk8zer0/npm-utils/yaml.js';
2
+ import { readJSONFile, writeJSONFile } from '@shgysk8zer0/npm-utils/json.js';
3
+ import { parseUnpkgURL, getUnpkgURL, getLatestVersion, UNPKG } from './utils.js';
4
+
5
+ export async function update(imports) {
6
+ let updated = false;
7
+
8
+ const entries = await Promise.all(Object.entries(imports)
9
+ .filter(([,val]) => val.startsWith(UNPKG))
10
+ .map(async ([key, val]) => {
11
+ const { scope, pkg, version: oldVersion, module } = parseUnpkgURL(val);
12
+ const version = await getLatestVersion({ scope, pkg });
13
+
14
+ if (! updated && version > oldVersion) {
15
+ updated = true;
16
+ }
17
+
18
+ return [key, getUnpkgURL({ scope, pkg, version, module })];
19
+ })
20
+ );
21
+
22
+ return { imports: Object.fromEntries(entries), updated };
23
+ }
24
+
25
+ export async function updateYAML(file) {
26
+ const importmap = await readYAMLFile(file);
27
+ const { updated, imports } = await update(importmap.imports);
28
+
29
+ if (updated) {
30
+ await writeYAMLFile(file, { ...importmap, imports: { ...importmap.imports, ...imports }});
31
+ return true;
32
+ } else {
33
+ return false;
34
+ }
35
+ }
36
+
37
+ export async function updateJSON(file) {
38
+ const importmap = await readJSONFile(file);
39
+ const { updated, imports } = await update(importmap.imports);
40
+
41
+ if (updated) {
42
+ await writeJSONFile(file, { ...importmap, imports: { ...importmap.imports, ...imports }});
43
+ return true;
44
+ } else {
45
+ return false;
46
+ }
47
+ }
package/update.js ADDED
@@ -0,0 +1,3 @@
1
+ import { unpkg } from '@shgysk8zer0/importmap';
2
+
3
+ await unpkg.updateJSON('importmap.json');
package/utils.js ADDED
@@ -0,0 +1,55 @@
1
+ export const UNPKG = 'https://unpkg.com/';
2
+
3
+ const cache = new Map();
4
+
5
+ export function parseUnpkgURL(src) {
6
+ const url = new URL(src, UNPKG);
7
+
8
+ if (! url.hostname === UNPKG || url.pathname.length === 1 || url.pathname === '/[object%20Object]') {
9
+ throw new Error(`${src} is not an unpkg URL.`);
10
+ } else {
11
+ const path = url.pathname.substr(1).split('/');
12
+
13
+ if (path.length === 0) {
14
+ throw new Error(`Invalid unpkg URL: ${src}`);
15
+ } else if (path.length !== 1 && path[0].startsWith('@')) {
16
+ const [pkg, version = null] = path[1].split('@');
17
+ return { scope: path[0], pkg, version, module: path.splice(2).join('/') };
18
+ } else {
19
+ const [pkg, version = null] = path[0].split('@');
20
+ return { scope: null, pkg, version, module: path.splice(1).join('/') };
21
+ }
22
+ }
23
+ }
24
+
25
+ export function getUnpkgURL({ scope, pkg, version, module = '' }) {
26
+ // console.log({ scope, pkg, version });
27
+ if (typeof pkg !== 'string' || pkg.length === 0) {
28
+ throw new TypeError('Package name must be a non-empty string.');
29
+ } else if (typeof version !== 'string' || version.length === 0) {
30
+ throw new TypeError('Version must be a non-empty string.');
31
+ } else if (typeof scope === 'string' && scope.length !== 0) {
32
+ return new URL(`/${scope}/${pkg}@${version}/${module}`, UNPKG).href;
33
+ } else {
34
+ return new URL(`/${pkg}@${version}/${module}`, UNPKG).href;
35
+ }
36
+ }
37
+
38
+ export async function getLatestVersion({ scope, pkg, signal } = {}) {
39
+ const path = typeof scope === 'string' ? `/${scope}/${pkg}/` : `/${pkg}/`;
40
+
41
+ if (cache.has(path)) {
42
+ return await cache.get(path);
43
+ } else {
44
+ const url = new URL(path, 'https://unpkg.com/');
45
+ url.searchParams.set('meta', '');
46
+
47
+ const promise = fetch(url, { method: 'HEAD', signal }).then(resp => {
48
+ const { version } = parseUnpkgURL(resp.url);
49
+ return version;
50
+ });
51
+
52
+ cache.set(path, promise);
53
+ return promise;
54
+ }
55
+ }
package/index.js DELETED
@@ -1,66 +0,0 @@
1
- import { writeFile } from 'node:fs/promises';
2
- import { createHash } from 'node:crypto';
3
- import { versions } from './versions.js';
4
-
5
- export const imports = {
6
- '@shgysk8zer0/kazoo/': `https://unpkg.com/@shgysk8zer0/kazoo@${versions['@shgysk8zer0/kazoo']}/`,
7
- '@shgysk8zer0/konami': `https://unpkg.com/@shgysk8zer0/konami@${versions['@shgysk8zer0/konami']}/konami.js`,
8
- '@shgysk8zer0/polyfills': `https://unpkg.com/@shgysk8zer0/polyfills@${versions['@shgysk8zer0/polyfills']}/all.min.js`,
9
- '@shgysk8zer0/polyfills/': `https://unpkg.com/@shgysk8zer0/polyfills@${versions['@shgysk8zer0/polyfills']}/`,
10
- '@shgysk8zer0/jswaggersheets': `https://unpkg.com/@shgysk8zer0/jswaggersheets@${versions['@shgysk8zer0/jswaggersheets']}/swagger.js`,
11
- '@shgysk8zer0/jswaggersheets/': `https://unpkg.com/@shgysk8zer0/jswaggersheets@${versions['@shgysk8zer0/jswaggersheets']}/`,
12
- '@shgysk8zer0/jss/': `https://unpkg.com/@shgysk8zer0/jss@${versions['@shgysk8zer0/jss/']}/`,
13
- '@shgysk8zer0/http-status': `https://unpkg.com/@shgysk8zer0/http-status@${versions['@shgysk8zer0/http-status']}/http-status.js`,
14
- '@shgysk8zer0/components/': `https://unpkg.com/@shgysk8zer0/components@${versions['@shgysk8zer0/components']}/`,
15
- '@kernvalley/components/': `https://unpkg.com/@kernvalley/components@${versions['@kernvalley/components']}/`,
16
- '@webcomponents/custom-elements': `https://unpkg.com/@webcomponents/custom-elements@${versions['@webcomponents/custom-elements']}/custom-elements.min.js`,
17
- 'leaflet': `https://unpkg.com/leaflet@${versions.leaflet}/dist/leaflet-src.esm.js`,
18
- 'firebase/': `https://www.gstatic.com/firebasejs/${versions.firebase}/`,
19
- 'urlpattern-polyfill': `https://unpkg.com/urlpattern-polyfill@${versions['urlpattern-polyfill']}/index.js`,
20
- 'highlight.js': `https://unpkg.com/@highlightjs/cdn-assets@${versions['highlight.js']}/es/highlight.min.js`,
21
- 'highlight.js/': `https://unpkg.com/@highlightjs/cdn-assets@${versions['highlight.js']}/`,
22
- 'marked': `https://unpkg.com/marked@${versions.marked}/src/marked.js`,
23
- 'marked-highlight': `https://unpkg.com/marked-highlight@${versions['marked-highlight']}/src/index.js`
24
- };
25
-
26
- export const scope = {};
27
- export const importmap = { imports, scope };
28
- export const ENCODING = 'utf8';
29
- export const ALGO = 'sha384';
30
-
31
- export function mergeWithImportmap({ imports = {}, scope = {}}) {
32
- return {
33
- imports: { ...importmap.imports, ...imports },
34
- scope: { ...importmap.scope, ...scope },
35
- };
36
- }
37
-
38
- export async function createImportmapJSON(path = 'importmap.json', {
39
- importmap = { imports, scope },
40
- spaces = 2,
41
- signal,
42
- } = {}) {
43
- await writeFile(path, JSON.stringify(importmap, null, spaces), { encoding: ENCODING, signal });
44
- }
45
-
46
- export function getImportmapIntegrity({
47
- importmap = { imports, scope },
48
- algo = ALGO,
49
- encoding = ENCODING,
50
- spaces = 2,
51
- } = {}) {
52
- const hash = createHash(algo);
53
- hash.update(JSON.stringify(importmap, null, spaces), encoding);
54
- return `${algo}-${hash.digest('base64')}`;
55
- }
56
-
57
- export function getImportMapScript({
58
- importmap = { imports, scope },
59
- algo = ALGO,
60
- encoding = ENCODING,
61
- spaces = 2,
62
- } = {}) {
63
- const integrity = getImportmapIntegrity({ importmap, algo, encoding, spaces });
64
- const json = JSON.stringify(importmap, null, spaces);
65
- return `<script type="importmap" integrity="${integrity}">${json}</script>`;
66
- }
package/versions.js DELETED
@@ -1,17 +0,0 @@
1
- export const versions = {
2
- '@shgysk8zer0/kazoo': '0.2.3',
3
- '@shgysk8zer0/konami': '1.1.0',
4
- '@shgysk8zer0/polyfills': '0.2.4',
5
- '@shgysk8zer0/components': '0.1.3',
6
- '@shgysk8zer0/http-status': '1.1.1',
7
- '@shgysk8zer0/jswaggersheets': '1.1.0',
8
- '@shgysk8zer0/jss': '1.0.1',
9
- '@kernvalley/components': '1.1.0',
10
- '@webcomponents/custom-elements': '1.6.0',
11
- 'leaflet': '1.9.4',
12
- 'firebase': '9.23.0',
13
- 'urlpattern-polyfill': '9.0.0',
14
- 'highlight.js': '11.8.0',
15
- 'marked': '5.1.0',
16
- 'marked-highlight': '2.0.1',
17
- };