publish-microfrontend 0.15.6-beta.5105 → 0.15.6-beta.5109

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/README.md CHANGED
@@ -26,6 +26,25 @@ No API key is necessary. Depending on your feed server you might want to use int
26
26
  npx publish-microfrontend --url <feed-url> --interactive
27
27
  ```
28
28
 
29
+ ## Config Options
30
+
31
+ For the `.microfrontendrc` file the following options exist:
32
+
33
+ - `url`: The URL of the feed service to use.
34
+ - `apiKey`: The API key to use when authenticating.
35
+ - `interactive`: Determines if the interactive login should be used to retrieve the authentication token / API key. Defaults to *false*.
36
+ - `cert`: The path to the custom certificate to use as CA.
37
+ - `mode`: The auth mode to use (can be 'none', 'basic', 'bearer', 'digest'). Defaults to *basic*.
38
+ - `from`: Describes the source location (can be 'local', 'remote', 'npm'). Defaults to *local*.
39
+ - `fields`: An object using key-value pairs to place additionally in the request's body.
40
+ - `headers`: An object using key-value pairs to place additionally in the request's header.
41
+
42
+ The config options can all be overriden by the CLI flags. They serve as the default values for the CLI flags.
43
+
44
+ ## CLI Flags
45
+
46
+ The CLI flags are a superset of the shown config options.
47
+
29
48
  ## License
30
49
 
31
50
  Piral is released using the MIT license. For more information see the [license file](./LICENSE).
package/lib/index.js CHANGED
@@ -14642,7 +14642,7 @@ var require_utils2 = __commonJS({
14642
14642
  function isDate(val) {
14643
14643
  return toString.call(val) === "[object Date]";
14644
14644
  }
14645
- function isFile(val) {
14645
+ function isFile2(val) {
14646
14646
  return toString.call(val) === "[object File]";
14647
14647
  }
14648
14648
  function isBlob(val) {
@@ -14731,7 +14731,7 @@ var require_utils2 = __commonJS({
14731
14731
  isPlainObject,
14732
14732
  isUndefined,
14733
14733
  isDate,
14734
- isFile,
14734
+ isFile: isFile2,
14735
14735
  isBlob,
14736
14736
  isFunction,
14737
14737
  isStream,
@@ -27070,6 +27070,7 @@ function fail(message, ...args2) {
27070
27070
 
27071
27071
  // src/utils.ts
27072
27072
  var import_glob = __toModule(require_glob());
27073
+ var import_fs2 = __toModule(require("fs"));
27073
27074
  var import_promises = __toModule(require("fs/promises"));
27074
27075
  var import_path3 = __toModule(require("path"));
27075
27076
 
@@ -27094,9 +27095,6 @@ var MemoryStream = class extends import_stream.Writable {
27094
27095
  var import_axios2 = __toModule(require_axios2());
27095
27096
  var import_form_data = __toModule(require_form_data());
27096
27097
  var import_https = __toModule(require("https"));
27097
- var import_fs = __toModule(require("fs"));
27098
- var import_os2 = __toModule(require("os"));
27099
- var import_path = __toModule(require("path"));
27100
27098
 
27101
27099
  // src/common.ts
27102
27100
  var import_os = __toModule(require("os"));
@@ -27167,6 +27165,23 @@ function getTokenInteractively(url, httpsAgent) {
27167
27165
  return tokenRetrievers[url];
27168
27166
  }
27169
27167
 
27168
+ // src/io.ts
27169
+ var import_os2 = __toModule(require("os"));
27170
+ var import_path = __toModule(require("path"));
27171
+ var import_fs = __toModule(require("fs"));
27172
+ function streamToFile(source, target) {
27173
+ const dest = (0, import_fs.createWriteStream)(target);
27174
+ return new Promise((resolve3, reject) => {
27175
+ source.pipe(dest);
27176
+ source.on("error", (err) => reject(err));
27177
+ dest.on("finish", () => resolve3([target]));
27178
+ });
27179
+ }
27180
+ function getRandomTempFile() {
27181
+ const rid = Math.random().toString(36).split(".").pop();
27182
+ return (0, import_path.join)((0, import_os2.tmpdir)(), `microfrontend_${rid}.tgz`);
27183
+ }
27184
+
27170
27185
  // src/http.ts
27171
27186
  function getMessage(body) {
27172
27187
  if (typeof body === "string") {
@@ -27185,14 +27200,6 @@ function getMessage(body) {
27185
27200
  }
27186
27201
  return "";
27187
27202
  }
27188
- function streamToFile(source, target) {
27189
- const dest = (0, import_fs.createWriteStream)(target);
27190
- return new Promise((resolve3, reject) => {
27191
- source.pipe(dest);
27192
- source.on("error", (err) => reject(err));
27193
- dest.on("finish", () => resolve3([target]));
27194
- });
27195
- }
27196
27203
  function downloadFile(url, ca) {
27197
27204
  return __async(this, null, function* () {
27198
27205
  const httpsAgent = ca ? new import_https.Agent({ ca }) : void 0;
@@ -27202,8 +27209,7 @@ function downloadFile(url, ca) {
27202
27209
  headers: standardHeaders,
27203
27210
  httpsAgent
27204
27211
  });
27205
- const rid = Math.random().toString(36).split(".").pop();
27206
- const target = (0, import_path.join)((0, import_os2.tmpdir)(), `microfrontend_${rid}.tgz`);
27212
+ const target = getRandomTempFile();
27207
27213
  return streamToFile(res.data, target);
27208
27214
  } catch (error) {
27209
27215
  logWarn("Failed HTTP GET requested: %s", error.message);
@@ -27368,19 +27374,22 @@ function findTarball(packageRef, target = ".", ...flags) {
27368
27374
  return ms.value;
27369
27375
  });
27370
27376
  }
27371
- function getCa(cert) {
27377
+ function createPackage(target = ".", ...flags) {
27372
27378
  return __async(this, null, function* () {
27373
- if (cert && typeof cert === "string") {
27374
- const statCert = yield (0, import_promises.stat)(cert).catch(() => void 0);
27375
- if (statCert == null ? void 0 : statCert.isFile()) {
27376
- const dir = (0, import_path3.dirname)(cert);
27377
- const file = (0, import_path3.basename)(cert);
27378
- return yield (0, import_promises.readFile)((0, import_path3.resolve)(dir, file));
27379
- }
27380
- }
27381
- return void 0;
27379
+ const ms = new MemoryStream();
27380
+ yield runNpmProcess(["pack", ...flags], target, ms);
27381
+ return ms.value;
27382
27382
  });
27383
27383
  }
27384
+ function onlyUnique(value, index, self) {
27385
+ return self.indexOf(value) === index;
27386
+ }
27387
+ function isFile(item) {
27388
+ return (0, import_fs2.statSync)(item).isFile();
27389
+ }
27390
+ function isDirectory(item) {
27391
+ return (0, import_fs2.statSync)(item).isDirectory();
27392
+ }
27384
27393
  function matchFiles(baseDir, pattern) {
27385
27394
  return new Promise((resolve3, reject) => {
27386
27395
  (0, import_glob.default)(pattern, {
@@ -27396,12 +27405,40 @@ function matchFiles(baseDir, pattern) {
27396
27405
  });
27397
27406
  });
27398
27407
  }
27408
+ function getCa(cert) {
27409
+ return __async(this, null, function* () {
27410
+ if (cert && typeof cert === "string") {
27411
+ const statCert = yield (0, import_promises.stat)(cert).catch(() => void 0);
27412
+ if (statCert == null ? void 0 : statCert.isFile()) {
27413
+ const dir = (0, import_path3.dirname)(cert);
27414
+ const file = (0, import_path3.basename)(cert);
27415
+ return yield (0, import_promises.readFile)((0, import_path3.resolve)(dir, file));
27416
+ }
27417
+ }
27418
+ return void 0;
27419
+ });
27420
+ }
27399
27421
  function getFiles(baseDir, sources, from, ca) {
27400
27422
  return __async(this, null, function* () {
27401
27423
  switch (from) {
27402
27424
  case "local": {
27403
27425
  const allFiles = yield Promise.all(sources.map((s) => matchFiles(baseDir, s)));
27404
- return allFiles.reduce((result, files) => [...result, ...files], []);
27426
+ const allMatches = allFiles.reduce((result, files) => [...result, ...files], []).filter(onlyUnique);
27427
+ if (allMatches.every(isDirectory)) {
27428
+ const dirs = allMatches.filter((m) => (0, import_fs2.existsSync)((0, import_path3.resolve)(m, "package.json")));
27429
+ return Promise.all(dirs.map((dir) => __async(this, null, function* () {
27430
+ const previousFiles = yield (0, import_promises.readdir)(dir);
27431
+ yield createPackage(dir);
27432
+ const currentFiles = yield (0, import_promises.readdir)(dir);
27433
+ const tarball = currentFiles.find((m) => !previousFiles.includes(m) && m.endsWith(".tgz"));
27434
+ const target = getRandomTempFile();
27435
+ const source = (0, import_path3.resolve)(dir, tarball);
27436
+ yield (0, import_promises.copyFile)(source, target);
27437
+ yield (0, import_promises.rm)(source);
27438
+ return target;
27439
+ })));
27440
+ }
27441
+ return allMatches.filter(isFile);
27405
27442
  }
27406
27443
  case "remote": {
27407
27444
  const allFiles = yield Promise.all(sources.map((s) => downloadFile(s, ca)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "publish-microfrontend",
3
- "version": "0.15.6-beta.5105",
3
+ "version": "0.15.6-beta.5109",
4
4
  "description": "A CLI for publishing micro frontends to a feed service.",
5
5
  "keywords": [
6
6
  "modules",
@@ -15,7 +15,7 @@
15
15
  "main": "lib/index.js",
16
16
  "typings": "lib/index.d.ts",
17
17
  "engines": {
18
- "node": ">=12.0"
18
+ "node": ">=14.0"
19
19
  },
20
20
  "files": [
21
21
  "lib",
@@ -46,7 +46,7 @@
46
46
  "@types/inquirer": "^6.0.0",
47
47
  "@types/jju": "^1.4.2",
48
48
  "@types/mime": "^2.0.0",
49
- "@types/node": "^12.7.2",
49
+ "@types/node": "^14.0.0",
50
50
  "@types/rc": "^1.1.0",
51
51
  "@types/rimraf": "^2.0.2",
52
52
  "@types/tar": "^4.0.0",
@@ -69,5 +69,5 @@
69
69
  "typescript": "^4.0.0",
70
70
  "yargs": "^15.0.0"
71
71
  },
72
- "gitHead": "fe9f4af00df8a9281ba22e253e4ace0171160768"
72
+ "gitHead": "e944c2737f6ede8187b599509961f2314d2534c3"
73
73
  }
package/src/http.ts CHANGED
@@ -2,12 +2,10 @@ import axios from 'axios';
2
2
  import FormData from 'form-data';
3
3
  import { Agent } from 'https';
4
4
  import { Stream } from 'stream';
5
- import { createWriteStream } from 'fs';
6
- import { tmpdir } from 'os';
7
- import { join } from 'path';
8
5
  import { logWarn } from './log';
9
6
  import { standardHeaders } from './common';
10
7
  import { getTokenInteractively } from './interactive';
8
+ import { getRandomTempFile, streamToFile } from './io';
11
9
 
12
10
  function getMessage(body: string | { message?: string }) {
13
11
  if (typeof body === 'string') {
@@ -36,14 +34,6 @@ export interface PostFormResult {
36
34
 
37
35
  export type FormDataObj = Record<string, string | [Buffer, string]>;
38
36
 
39
- function streamToFile(source: Stream, target: string) {
40
- const dest = createWriteStream(target);
41
- return new Promise<Array<string>>((resolve, reject) => {
42
- source.pipe(dest);
43
- source.on('error', (err) => reject(err));
44
- dest.on('finish', () => resolve([target]));
45
- });
46
- }
47
37
 
48
38
  export async function downloadFile(url: string, ca?: Buffer): Promise<Array<string>> {
49
39
  const httpsAgent = ca ? new Agent({ ca }) : undefined;
@@ -54,8 +44,7 @@ export async function downloadFile(url: string, ca?: Buffer): Promise<Array<stri
54
44
  headers: standardHeaders,
55
45
  httpsAgent,
56
46
  });
57
- const rid = Math.random().toString(36).split('.').pop();
58
- const target = join(tmpdir(), `microfrontend_${rid}.tgz`);
47
+ const target = getRandomTempFile();
59
48
  return streamToFile(res.data, target);
60
49
  } catch (error) {
61
50
  logWarn('Failed HTTP GET requested: %s', error.message);
package/src/io.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { tmpdir } from 'os';
2
+ import { join } from 'path';
3
+ import { Stream } from 'stream';
4
+ import { createWriteStream } from 'fs';
5
+
6
+ export function streamToFile(source: Stream, target: string) {
7
+ const dest = createWriteStream(target);
8
+ return new Promise<Array<string>>((resolve, reject) => {
9
+ source.pipe(dest);
10
+ source.on('error', (err) => reject(err));
11
+ dest.on('finish', () => resolve([target]));
12
+ });
13
+ }
14
+
15
+ export function getRandomTempFile() {
16
+ const rid = Math.random().toString(36).split('.').pop();
17
+ return join(tmpdir(), `microfrontend_${rid}.tgz`);
18
+ }
package/src/utils.ts CHANGED
@@ -1,36 +1,42 @@
1
1
  import glob from 'glob';
2
- import { stat, readFile } from 'fs/promises';
2
+ import { existsSync, statSync } from 'fs';
3
+ import { stat, readFile, readdir, copyFile, rm } from 'fs/promises';
3
4
  import { dirname, basename, resolve } from 'path';
4
5
  import { MemoryStream } from 'piral-cli/src/common/MemoryStream';
5
6
  import { downloadFile } from './http';
6
7
  import { runCommand } from './scripts';
8
+ import { getRandomTempFile } from './io';
7
9
 
8
10
  function runNpmProcess(args: Array<string>, target: string, output?: NodeJS.WritableStream) {
9
- const cwd = resolve(process.cwd(), target);
10
- return runCommand('npm', args, cwd, output);
11
- }
11
+ const cwd = resolve(process.cwd(), target);
12
+ return runCommand('npm', args, cwd, output);
13
+ }
12
14
 
13
15
  async function findTarball(packageRef: string, target = '.', ...flags: Array<string>) {
14
- const ms = new MemoryStream();
15
- await runNpmProcess(['view', packageRef, 'dist.tarball', ...flags], target, ms);
16
- return ms.value;
17
- }
16
+ const ms = new MemoryStream();
17
+ await runNpmProcess(['view', packageRef, 'dist.tarball', ...flags], target, ms);
18
+ return ms.value;
19
+ }
18
20
 
19
- export async function getCa(cert: string | undefined): Promise<Buffer | undefined> {
20
- if (cert && typeof cert === 'string') {
21
- const statCert = await stat(cert).catch(() => undefined);
21
+ async function createPackage(target = '.', ...flags: Array<string>) {
22
+ const ms = new MemoryStream();
23
+ await runNpmProcess(['pack', ...flags], target, ms);
24
+ return ms.value;
25
+ }
22
26
 
23
- if (statCert?.isFile()) {
24
- const dir = dirname(cert);
25
- const file = basename(cert);
26
- return await readFile(resolve(dir, file));
27
- }
28
- }
27
+ function onlyUnique<T>(value: T, index: number, self: Array<T>) {
28
+ return self.indexOf(value) === index;
29
+ }
29
30
 
30
- return undefined;
31
+ function isFile(item: string) {
32
+ return statSync(item).isFile();
33
+ }
34
+
35
+ function isDirectory(item: string) {
36
+ return statSync(item).isDirectory();
31
37
  }
32
38
 
33
- export function matchFiles(baseDir: string, pattern: string) {
39
+ function matchFiles(baseDir: string, pattern: string) {
34
40
  return new Promise<Array<string>>((resolve, reject) => {
35
41
  glob(
36
42
  pattern,
@@ -50,16 +56,47 @@ export function matchFiles(baseDir: string, pattern: string) {
50
56
  });
51
57
  }
52
58
 
53
- export async function getFiles(baseDir: string, sources: Array<string>, from: string, ca: Buffer): Promise<Array<string>> {
59
+ export async function getCa(cert: string | undefined): Promise<Buffer | undefined> {
60
+ if (cert && typeof cert === 'string') {
61
+ const statCert = await stat(cert).catch(() => undefined);
62
+
63
+ if (statCert?.isFile()) {
64
+ const dir = dirname(cert);
65
+ const file = basename(cert);
66
+ return await readFile(resolve(dir, file));
67
+ }
68
+ }
69
+
70
+ return undefined;
71
+ }
72
+
73
+ export async function getFiles(
74
+ baseDir: string,
75
+ sources: Array<string>,
76
+ from: string,
77
+ ca: Buffer,
78
+ ): Promise<Array<string>> {
54
79
  switch (from) {
55
80
  case 'local': {
56
81
  const allFiles = await Promise.all(sources.map((s) => matchFiles(baseDir, s)));
57
- // TODO:
58
- // - Reduced files should be unique.
59
- // - can be a mix of directories and files - if files are matched take those, otherwise take directories
60
- // - for all matched directories look up if a `package.json` exists - if yes, run "npm pack" and replace the directory by the created npm package
61
- // Finally return these files (created npm packages should be taken from a tmp directory, following the download approach below)
62
- return allFiles.reduce((result, files) => [...result, ...files], []);
82
+ const allMatches = allFiles.reduce((result, files) => [...result, ...files], []).filter(onlyUnique);
83
+
84
+ if (allMatches.every(isDirectory)) {
85
+ const dirs = allMatches.filter(m => existsSync(resolve(m, 'package.json')));
86
+ return Promise.all(dirs.map(async dir => {
87
+ const previousFiles = await readdir(dir);
88
+ await createPackage(dir);
89
+ const currentFiles = await readdir(dir);
90
+ const tarball = currentFiles.find(m => !previousFiles.includes(m) && m.endsWith('.tgz'));
91
+ const target = getRandomTempFile();
92
+ const source = resolve(dir, tarball);
93
+ await copyFile(source, target);
94
+ await rm(source);
95
+ return target;
96
+ }));
97
+ }
98
+
99
+ return allMatches.filter(isFile);
63
100
  }
64
101
  case 'remote': {
65
102
  const allFiles = await Promise.all(sources.map((s) => downloadFile(s, ca)));