mirror of
https://github.com/wkulhanek/bonob.git
synced 2025-12-21 17:33:29 +01:00
Artist images showing in list
This commit is contained in:
@@ -10,6 +10,7 @@
|
|||||||
"@types/express": "^4.17.11",
|
"@types/express": "^4.17.11",
|
||||||
"@types/morgan": "^1.9.2",
|
"@types/morgan": "^1.9.2",
|
||||||
"@types/node": "^14.14.22",
|
"@types/node": "^14.14.22",
|
||||||
|
"@types/sharp": "^0.27.1",
|
||||||
"@types/underscore": "1.10.24",
|
"@types/underscore": "1.10.24",
|
||||||
"@types/uuid": "^8.3.0",
|
"@types/uuid": "^8.3.0",
|
||||||
"axios": "^0.21.1",
|
"axios": "^0.21.1",
|
||||||
@@ -19,6 +20,7 @@
|
|||||||
"fp-ts": "^2.9.5",
|
"fp-ts": "^2.9.5",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"node-html-parser": "^2.1.0",
|
"node-html-parser": "^2.1.0",
|
||||||
|
"sharp": "^0.27.2",
|
||||||
"soap": "^0.36.0",
|
"soap": "^0.36.0",
|
||||||
"ts-md5": "^1.2.7",
|
"ts-md5": "^1.2.7",
|
||||||
"typescript": "^4.1.3",
|
"typescript": "^4.1.3",
|
||||||
|
|||||||
@@ -25,7 +25,6 @@ export type AuthFailure = {
|
|||||||
export type ArtistSummary = {
|
export type ArtistSummary = {
|
||||||
id: string;
|
id: string;
|
||||||
name: string;
|
name: string;
|
||||||
image: Images;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type Images = {
|
export type Images = {
|
||||||
@@ -41,6 +40,7 @@ export const NO_IMAGES: Images = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type Artist = ArtistSummary & {
|
export type Artist = ArtistSummary & {
|
||||||
|
image: Images
|
||||||
albums: AlbumSummary[];
|
albums: AlbumSummary[];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,7 +95,6 @@ export type AlbumQuery = Paging & {
|
|||||||
export const artistToArtistSummary = (it: Artist): ArtistSummary => ({
|
export const artistToArtistSummary = (it: Artist): ArtistSummary => ({
|
||||||
id: it.id,
|
id: it.id,
|
||||||
name: it.name,
|
name: it.name,
|
||||||
image: it.image,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
export const albumToAlbumSummary = (it: Album): AlbumSummary => ({
|
export const albumToAlbumSummary = (it: Album): AlbumSummary => ({
|
||||||
@@ -145,5 +144,5 @@ export interface MusicLibrary {
|
|||||||
trackId: string;
|
trackId: string;
|
||||||
range: string | undefined;
|
range: string | undefined;
|
||||||
}): Promise<Stream>;
|
}): Promise<Stream>;
|
||||||
coverArt(id: string, size?: number): Promise<CoverArt>;
|
coverArt(id: string, type: "album" | "artist", size?: number): Promise<CoverArt | undefined>;
|
||||||
}
|
}
|
||||||
|
|||||||
136
src/navidrome.ts
136
src/navidrome.ts
@@ -19,11 +19,22 @@ import {
|
|||||||
NO_IMAGES,
|
NO_IMAGES,
|
||||||
} from "./music_service";
|
} from "./music_service";
|
||||||
import X2JS from "x2js";
|
import X2JS from "x2js";
|
||||||
|
import sharp from "sharp";
|
||||||
|
|
||||||
import axios, { AxiosRequestConfig } from "axios";
|
import axios, { AxiosRequestConfig } from "axios";
|
||||||
import { Encryption } from "./encryption";
|
import { Encryption } from "./encryption";
|
||||||
import randomString from "./random_string";
|
import randomString from "./random_string";
|
||||||
|
|
||||||
|
export const BROWSER_HEADERS = {
|
||||||
|
accept:
|
||||||
|
"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
||||||
|
"accept-encoding": "gzip, deflate, br",
|
||||||
|
"accept-language": "en-GB,en;q=0.5",
|
||||||
|
"upgrade-insecure-requests": "1",
|
||||||
|
"user-agent":
|
||||||
|
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:86.0) Gecko/20100101 Firefox/86.0",
|
||||||
|
};
|
||||||
|
|
||||||
export const t = (password: string, s: string) =>
|
export const t = (password: string, s: string) =>
|
||||||
Md5.hashStr(`${password}${s}`);
|
Md5.hashStr(`${password}${s}`);
|
||||||
|
|
||||||
@@ -35,8 +46,12 @@ export const t_and_s = (password: string) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const isDodgyImage = (url: string) =>
|
export const DODGY_IMAGE_NAME = "2a96cbd8b46e442fc41c2b86b821562f.png";
|
||||||
url.endsWith("2a96cbd8b46e442fc41c2b86b821562f.png");
|
|
||||||
|
export const isDodgyImage = (url: string) => url.endsWith(DODGY_IMAGE_NAME);
|
||||||
|
|
||||||
|
export const validate = (url: string | undefined) =>
|
||||||
|
url && !isDodgyImage(url) ? url : undefined;
|
||||||
|
|
||||||
export type SubconicEnvelope = {
|
export type SubconicEnvelope = {
|
||||||
"subsonic-response": SubsonicResponse;
|
"subsonic-response": SubsonicResponse;
|
||||||
@@ -282,9 +297,9 @@ export class Navidrome implements MusicService {
|
|||||||
id,
|
id,
|
||||||
}).then((it) => ({
|
}).then((it) => ({
|
||||||
image: {
|
image: {
|
||||||
small: it.artistInfo.smallImageUrl,
|
small: validate(it.artistInfo.smallImageUrl),
|
||||||
medium: it.artistInfo.mediumImageUrl,
|
medium: validate(it.artistInfo.mediumImageUrl),
|
||||||
large: it.artistInfo.largeImageUrl,
|
large: validate(it.artistInfo.largeImageUrl),
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
@@ -309,7 +324,7 @@ export class Navidrome implements MusicService {
|
|||||||
.then((it) => ({
|
.then((it) => ({
|
||||||
id: it._id,
|
id: it._id,
|
||||||
name: it._name,
|
name: it._name,
|
||||||
albums: it.album.map((album) => ({
|
albums: (it.album || []).map((album) => ({
|
||||||
id: album._id,
|
id: album._id,
|
||||||
name: album._name,
|
name: album._name,
|
||||||
year: album._year,
|
year: album._year,
|
||||||
@@ -317,6 +332,28 @@ export class Navidrome implements MusicService {
|
|||||||
})),
|
})),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
getArtistWithInfo = (credentials: Credentials, id: string) =>
|
||||||
|
Promise.all([
|
||||||
|
this.getArtist(credentials, id),
|
||||||
|
this.getArtistInfo(credentials, id),
|
||||||
|
]).then(([artist, artistInfo]) => ({
|
||||||
|
id: artist.id,
|
||||||
|
name: artist.name,
|
||||||
|
image: artistInfo.image,
|
||||||
|
albums: artist.albums,
|
||||||
|
}));
|
||||||
|
|
||||||
|
getCoverArt = (credentials: Credentials, id: string, size?: number) =>
|
||||||
|
this.get(
|
||||||
|
credentials,
|
||||||
|
"/rest/getCoverArt",
|
||||||
|
{ id, size },
|
||||||
|
{
|
||||||
|
headers: { "User-Agent": "bonob" },
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
async login(token: string) {
|
async login(token: string) {
|
||||||
const navidrome = this;
|
const navidrome = this;
|
||||||
const credentials: Credentials = this.parseToken(token);
|
const credentials: Credentials = this.parseToken(token);
|
||||||
@@ -326,36 +363,12 @@ export class Navidrome implements MusicService {
|
|||||||
navidrome
|
navidrome
|
||||||
.getArtists(credentials)
|
.getArtists(credentials)
|
||||||
.then(slice2(q))
|
.then(slice2(q))
|
||||||
.then(([page, total]) =>
|
.then(([page, total]) => ({
|
||||||
Promise.all(
|
|
||||||
page.map((idName: IdName) =>
|
|
||||||
navidrome
|
|
||||||
.getArtistInfo(credentials, idName.id)
|
|
||||||
.then((artistInfo) => ({
|
|
||||||
total,
|
total,
|
||||||
result: {
|
results: page.map((it) => ({ id: it.id, name: it.name })),
|
||||||
id: idName.id,
|
|
||||||
name: idName.name,
|
|
||||||
image: artistInfo.image,
|
|
||||||
},
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.then((resultWithInfo) => ({
|
|
||||||
total: resultWithInfo[0]?.total || 0,
|
|
||||||
results: resultWithInfo.map((it) => it.result),
|
|
||||||
})),
|
})),
|
||||||
artist: async (id: string): Promise<Artist> =>
|
artist: async (id: string): Promise<Artist> =>
|
||||||
Promise.all([
|
navidrome.getArtistWithInfo(credentials, id),
|
||||||
navidrome.getArtist(credentials, id),
|
|
||||||
navidrome.getArtistInfo(credentials, id),
|
|
||||||
]).then(([artist, artistInfo]) => ({
|
|
||||||
id: artist.id,
|
|
||||||
name: artist.name,
|
|
||||||
image: artistInfo.image,
|
|
||||||
albums: artist.albums,
|
|
||||||
})),
|
|
||||||
albums: (q: AlbumQuery): Promise<Result<AlbumSummary>> =>
|
albums: (q: AlbumQuery): Promise<Result<AlbumSummary>> =>
|
||||||
navidrome
|
navidrome
|
||||||
.getJSON<GetAlbumListResponse>(credentials, "/rest/getAlbumList", {
|
.getJSON<GetAlbumListResponse>(credentials, "/rest/getAlbumList", {
|
||||||
@@ -372,7 +385,7 @@ export class Navidrome implements MusicService {
|
|||||||
size: MAX_ALBUM_LIST,
|
size: MAX_ALBUM_LIST,
|
||||||
offset: 0,
|
offset: 0,
|
||||||
})
|
})
|
||||||
.then((response) => response.albumList.album)
|
.then((response) => response.albumList.album || [])
|
||||||
.then((albumList) =>
|
.then((albumList) =>
|
||||||
albumList.map((album) => ({
|
albumList.map((album) => ({
|
||||||
id: album._id,
|
id: album._id,
|
||||||
@@ -405,7 +418,7 @@ export class Navidrome implements MusicService {
|
|||||||
})
|
})
|
||||||
.then((it) => it.album)
|
.then((it) => it.album)
|
||||||
.then((album) =>
|
.then((album) =>
|
||||||
album.song.map((song) => asTrack(asAlbum(album), song))
|
(album.song || []).map((song) => asTrack(asAlbum(album), song))
|
||||||
),
|
),
|
||||||
track: (trackId: string) =>
|
track: (trackId: string) =>
|
||||||
navidrome
|
navidrome
|
||||||
@@ -455,21 +468,54 @@ export class Navidrome implements MusicService {
|
|||||||
},
|
},
|
||||||
data: Buffer.from(res.data, "binary"),
|
data: Buffer.from(res.data, "binary"),
|
||||||
})),
|
})),
|
||||||
coverArt: async (id: string, size?: number) =>
|
coverArt: async (id: string, type: "album" | "artist", size?: number) => {
|
||||||
navidrome
|
if (type == "album") {
|
||||||
.get(
|
return navidrome.getCoverArt(credentials, id, size).then((res) => ({
|
||||||
credentials,
|
contentType: res.headers["content-type"],
|
||||||
"/rest/getCoverArt",
|
data: Buffer.from(res.data, "binary"),
|
||||||
{ id, size },
|
}));
|
||||||
{
|
} else {
|
||||||
headers: { "User-Agent": "bonob" },
|
return navidrome.getArtistWithInfo(credentials, id).then((artist) => {
|
||||||
|
if (artist.image.large) {
|
||||||
|
console.log(`fetching from ${artist.image.large}`);
|
||||||
|
return axios
|
||||||
|
.get(artist.image.large!, {
|
||||||
|
headers: BROWSER_HEADERS,
|
||||||
responseType: "arraybuffer",
|
responseType: "arraybuffer",
|
||||||
|
})
|
||||||
|
.then((res) => {
|
||||||
|
const image = Buffer.from(res.data, "binary");
|
||||||
|
if (size) {
|
||||||
|
return sharp(image)
|
||||||
|
.resize(size)
|
||||||
|
.toBuffer()
|
||||||
|
.then((resized) => ({
|
||||||
|
contentType: res.headers["content-type"],
|
||||||
|
data: resized,
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
return {
|
||||||
|
contentType: res.headers["content-type"],
|
||||||
|
data: image,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
)
|
});
|
||||||
|
} else if (artist.albums.length > 0) {
|
||||||
|
console.log(
|
||||||
|
`gettin cover art for artist album id = ${artist.albums[0]!.id}`
|
||||||
|
);
|
||||||
|
return navidrome
|
||||||
|
.getCoverArt(credentials, artist.albums[0]!.id, size)
|
||||||
.then((res) => ({
|
.then((res) => ({
|
||||||
contentType: res.headers["content-type"],
|
contentType: res.headers["content-type"],
|
||||||
data: Buffer.from(res.data, "binary"),
|
data: Buffer.from(res.data, "binary"),
|
||||||
})),
|
}));
|
||||||
|
} else {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return Promise.resolve(musicLibrary);
|
return Promise.resolve(musicLibrary);
|
||||||
|
|||||||
@@ -149,25 +149,35 @@ function server(
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get("/album/:albumId/art/size/:size", (req, res) => {
|
app.get("/:type/:id/art/size/:size", (req, res) => {
|
||||||
const authToken = accessTokens.authTokenFor(
|
const authToken = accessTokens.authTokenFor(
|
||||||
req.query[BONOB_ACCESS_TOKEN_HEADER] as string
|
req.query[BONOB_ACCESS_TOKEN_HEADER] as string
|
||||||
);
|
);
|
||||||
|
const type = req.params["type"]!;
|
||||||
|
const id = req.params["id"]!;
|
||||||
|
const size = Number.parseInt(req.params["size"]!);
|
||||||
if (!authToken) {
|
if (!authToken) {
|
||||||
return res.status(401).send();
|
return res.status(401).send();
|
||||||
|
} else if(type != "artist" && type != "album") {
|
||||||
|
return res.status(400).send();
|
||||||
} else {
|
} else {
|
||||||
return musicService
|
return musicService
|
||||||
.login(authToken)
|
.login(authToken)
|
||||||
.then((it) =>
|
.then((it) =>
|
||||||
it.coverArt(
|
it.coverArt(
|
||||||
req.params["albumId"]!,
|
id,
|
||||||
Number.parseInt(req.params["size"]!)
|
type,
|
||||||
|
size
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then((coverArt) => {
|
.then((coverArt) => {
|
||||||
|
if(coverArt) {
|
||||||
res.status(200);
|
res.status(200);
|
||||||
res.setHeader("content-type", coverArt.contentType);
|
res.setHeader("content-type", coverArt.contentType);
|
||||||
res.send(coverArt.data);
|
res.send(coverArt.data);
|
||||||
|
} else {
|
||||||
|
res.status(404).send();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
32
src/smapi.ts
32
src/smapi.ts
@@ -8,6 +8,7 @@ import logger from "./logger";
|
|||||||
import { LinkCodes } from "./link_codes";
|
import { LinkCodes } from "./link_codes";
|
||||||
import {
|
import {
|
||||||
AlbumSummary,
|
AlbumSummary,
|
||||||
|
ArtistSummary,
|
||||||
MusicLibrary,
|
MusicLibrary,
|
||||||
MusicService,
|
MusicService,
|
||||||
slice2,
|
slice2,
|
||||||
@@ -210,7 +211,19 @@ const genre = (genre: string) => ({
|
|||||||
title: genre,
|
title: genre,
|
||||||
});
|
});
|
||||||
|
|
||||||
export const defaultAlbumArtURI = (webAddress: string, accessToken: string, album: AlbumSummary) => `${webAddress}/album/${album.id}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`
|
export const defaultAlbumArtURI = (
|
||||||
|
webAddress: string,
|
||||||
|
accessToken: string,
|
||||||
|
album: AlbumSummary
|
||||||
|
) =>
|
||||||
|
`${webAddress}/album/${album.id}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`;
|
||||||
|
|
||||||
|
export const defaultArtistArtURI = (
|
||||||
|
webAddress: string,
|
||||||
|
accessToken: string,
|
||||||
|
artist: ArtistSummary
|
||||||
|
) =>
|
||||||
|
`${webAddress}/artist/${artist.id}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`;
|
||||||
|
|
||||||
const album = (
|
const album = (
|
||||||
webAddress: string,
|
webAddress: string,
|
||||||
@@ -223,7 +236,11 @@ const album = (
|
|||||||
albumArtURI: defaultAlbumArtURI(webAddress, accessToken, album),
|
albumArtURI: defaultAlbumArtURI(webAddress, accessToken, album),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const track = (webAddress: string, accessToken: string, track: Track) => ({
|
export const track = (
|
||||||
|
webAddress: string,
|
||||||
|
accessToken: string,
|
||||||
|
track: Track
|
||||||
|
) => ({
|
||||||
itemType: "track",
|
itemType: "track",
|
||||||
id: `track:${track.id}`,
|
id: `track:${track.id}`,
|
||||||
mimeType: track.mimeType,
|
mimeType: track.mimeType,
|
||||||
@@ -382,19 +399,20 @@ function bindSmapiSoapServiceToExpress(
|
|||||||
total: 3,
|
total: 3,
|
||||||
});
|
});
|
||||||
case "artists":
|
case "artists":
|
||||||
return await musicLibrary.artists(paging).then((result) =>
|
return await musicLibrary.artists(paging).then((result) => {
|
||||||
getMetadataResult({
|
const accessToken = accessTokens.mint(authToken);
|
||||||
|
return getMetadataResult({
|
||||||
mediaCollection: result.results.map((it) => ({
|
mediaCollection: result.results.map((it) => ({
|
||||||
itemType: "artist",
|
itemType: "artist",
|
||||||
id: `artist:${it.id}`,
|
id: `artist:${it.id}`,
|
||||||
artistId: it.id,
|
artistId: it.id,
|
||||||
title: it.name,
|
title: it.name,
|
||||||
albumArtURI: it.image.small,
|
albumArtURI: defaultArtistArtURI(webAddress, accessToken, it),
|
||||||
})),
|
})),
|
||||||
index: paging._index,
|
index: paging._index,
|
||||||
total: result.total,
|
total: result.total,
|
||||||
})
|
});
|
||||||
);
|
});
|
||||||
case "albums":
|
case "albums":
|
||||||
return await musicLibrary.albums(paging).then((result) => {
|
return await musicLibrary.albums(paging).then((result) => {
|
||||||
const accessToken = accessTokens.mint(authToken);
|
const accessToken = accessTokens.mint(authToken);
|
||||||
|
|||||||
@@ -56,7 +56,6 @@ describe("InMemoryMusicService", () => {
|
|||||||
expect(artistToArtistSummary(artist)).toEqual({
|
expect(artistToArtistSummary(artist)).toEqual({
|
||||||
id: artist.id,
|
id: artist.id,
|
||||||
name: artist.name,
|
name: artist.name,
|
||||||
image: artist.image,
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ export class InMemoryMusicService implements MusicService {
|
|||||||
trackId: string;
|
trackId: string;
|
||||||
range: string | undefined;
|
range: string | undefined;
|
||||||
}) => Promise.reject("unsupported operation"),
|
}) => Promise.reject("unsupported operation"),
|
||||||
coverArt: (id: string, size?: number) => Promise.reject(`Cannot retrieve coverArt for ${id}, size ${size}`)
|
coverArt: (id: string, _: "album" | "artist", size?: number) => Promise.reject(`Cannot retrieve coverArt for ${id}, size ${size}`)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,21 @@
|
|||||||
import { Md5 } from "ts-md5/dist/md5";
|
import { Md5 } from "ts-md5/dist/md5";
|
||||||
import { v4 as uuid } from "uuid";
|
import { v4 as uuid } from "uuid";
|
||||||
|
|
||||||
import { isDodgyImage, Navidrome, t } from "../src/navidrome";
|
import {
|
||||||
|
isDodgyImage,
|
||||||
|
Navidrome,
|
||||||
|
t,
|
||||||
|
BROWSER_HEADERS,
|
||||||
|
DODGY_IMAGE_NAME,
|
||||||
|
} from "../src/navidrome";
|
||||||
import encryption from "../src/encryption";
|
import encryption from "../src/encryption";
|
||||||
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
jest.mock("axios");
|
jest.mock("axios");
|
||||||
|
|
||||||
|
import sharp from "sharp";
|
||||||
|
jest.mock("sharp");
|
||||||
|
|
||||||
import randomString from "../src/random_string";
|
import randomString from "../src/random_string";
|
||||||
import {
|
import {
|
||||||
Album,
|
Album,
|
||||||
@@ -178,6 +187,7 @@ describe("Navidrome", () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
jest.resetAllMocks();
|
||||||
|
|
||||||
axios.get = mockGET;
|
axios.get = mockGET;
|
||||||
|
|
||||||
@@ -286,6 +296,64 @@ describe("Navidrome", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("getting an artist", () => {
|
describe("getting an artist", () => {
|
||||||
|
describe("when the artist exists and has dodgy looking artist image uris", () => {
|
||||||
|
const album1: Album = anAlbum();
|
||||||
|
|
||||||
|
const album2: Album = anAlbum();
|
||||||
|
|
||||||
|
const artist: Artist = anArtist({
|
||||||
|
albums: [album1, album2],
|
||||||
|
image: {
|
||||||
|
small: `http://localhost:80/${DODGY_IMAGE_NAME}`,
|
||||||
|
medium: `http://localhost:80/${DODGY_IMAGE_NAME}`,
|
||||||
|
large: `http://localhost:80/${DODGY_IMAGE_NAME}`,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(artistXml(artist))))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(artist.image)))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return remove the dodgy looking image uris and return undefined", async () => {
|
||||||
|
const result: Artist = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.artist(artist.id));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: artist.id,
|
||||||
|
name: artist.name,
|
||||||
|
image: {
|
||||||
|
small: undefined,
|
||||||
|
medium: undefined,
|
||||||
|
large: undefined,
|
||||||
|
},
|
||||||
|
albums: artist.albums,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artist.id,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
||||||
|
params: {
|
||||||
|
id: artist.id,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("when the artist exists and has multiple albums", () => {
|
describe("when the artist exists and has multiple albums", () => {
|
||||||
const album1: Album = anAlbum();
|
const album1: Album = anAlbum();
|
||||||
@@ -385,6 +453,51 @@ describe("Navidrome", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when the artist exists and has no albums", () => {
|
||||||
|
const artist: Artist = anArtist({
|
||||||
|
albums: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(artistXml(artist))))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(artist.image)))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return it", async () => {
|
||||||
|
const result: Artist = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.artist(artist.id));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
id: artist.id,
|
||||||
|
name: artist.name,
|
||||||
|
image: artist.image,
|
||||||
|
albums: [],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artist.id,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
||||||
|
params: {
|
||||||
|
id: artist.id,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("getting artists", () => {
|
describe("getting artists", () => {
|
||||||
@@ -450,19 +563,7 @@ describe("Navidrome", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockGET
|
mockGET
|
||||||
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
.mockImplementationOnce(() => Promise.resolve(ok(getArtistsXml)))
|
.mockImplementationOnce(() => Promise.resolve(ok(getArtistsXml)));
|
||||||
.mockImplementationOnce(() =>
|
|
||||||
Promise.resolve(ok(artistInfoXml(artist1.image)))
|
|
||||||
)
|
|
||||||
.mockImplementationOnce(() =>
|
|
||||||
Promise.resolve(ok(artistInfoXml(artist2.image)))
|
|
||||||
)
|
|
||||||
.mockImplementationOnce(() =>
|
|
||||||
Promise.resolve(ok(artistInfoXml(artist3.image)))
|
|
||||||
)
|
|
||||||
.mockImplementationOnce(() =>
|
|
||||||
Promise.resolve(ok(artistInfoXml(artist4.image)))
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return all the artists", async () => {
|
it("should return all the artists", async () => {
|
||||||
@@ -476,7 +577,6 @@ describe("Navidrome", () => {
|
|||||||
(it) => ({
|
(it) => ({
|
||||||
id: it.id,
|
id: it.id,
|
||||||
name: it.name,
|
name: it.name,
|
||||||
image: it.image,
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -489,34 +589,6 @@ describe("Navidrome", () => {
|
|||||||
params: authParams,
|
params: authParams,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
|
||||||
params: {
|
|
||||||
id: artist1.id,
|
|
||||||
...authParams,
|
|
||||||
},
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
|
||||||
params: {
|
|
||||||
id: artist2.id,
|
|
||||||
...authParams,
|
|
||||||
},
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
|
||||||
params: {
|
|
||||||
id: artist3.id,
|
|
||||||
...authParams,
|
|
||||||
},
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
|
||||||
params: {
|
|
||||||
id: artist4.id,
|
|
||||||
...authParams,
|
|
||||||
},
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -524,13 +596,7 @@ describe("Navidrome", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockGET
|
mockGET
|
||||||
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
.mockImplementationOnce(() => Promise.resolve(ok(getArtistsXml)))
|
.mockImplementationOnce(() => Promise.resolve(ok(getArtistsXml)));
|
||||||
.mockImplementationOnce(() =>
|
|
||||||
Promise.resolve(ok(artistInfoXml(artist2.image)))
|
|
||||||
)
|
|
||||||
.mockImplementationOnce(() =>
|
|
||||||
Promise.resolve(ok(artistInfoXml(artist3.image)))
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("should return only the correct page of artists", async () => {
|
it("should return only the correct page of artists", async () => {
|
||||||
@@ -543,7 +609,6 @@ describe("Navidrome", () => {
|
|||||||
const expectedResults = [artist2, artist3].map((it) => ({
|
const expectedResults = [artist2, artist3].map((it) => ({
|
||||||
id: it.id,
|
id: it.id,
|
||||||
name: it.name,
|
name: it.name,
|
||||||
image: it.image,
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
expect(artists).toEqual({ results: expectedResults, total: 4 });
|
expect(artists).toEqual({ results: expectedResults, total: 4 });
|
||||||
@@ -552,20 +617,6 @@ describe("Navidrome", () => {
|
|||||||
params: authParams,
|
params: authParams,
|
||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
|
||||||
params: {
|
|
||||||
id: artist2.id,
|
|
||||||
...authParams,
|
|
||||||
},
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtistInfo`, {
|
|
||||||
params: {
|
|
||||||
id: artist3.id,
|
|
||||||
...authParams,
|
|
||||||
},
|
|
||||||
headers,
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -661,9 +712,48 @@ describe("Navidrome", () => {
|
|||||||
headers,
|
headers,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("when the artist has only no albums", () => {
|
||||||
|
const artist1 = anArtist({
|
||||||
|
name: "one hit wonder",
|
||||||
|
albums: [],
|
||||||
|
});
|
||||||
|
const artists = [artist1];
|
||||||
|
const albums = artists.flatMap((artist) => artist.albums);
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(albumListXml(asArtistAlbumPairs(artists))))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the album", async () => {
|
||||||
|
const paging = { _index: 0, _count: 500 };
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.albums(paging));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
results: albums,
|
||||||
|
total: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getAlbumList`, {
|
||||||
|
params: {
|
||||||
|
type: "alphabeticalByArtist",
|
||||||
|
size: 500,
|
||||||
|
offset: 0,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("when there are less than 500 albums", () => {
|
describe("when there are less than 500 albums", () => {
|
||||||
const artist1 = anArtist({
|
const artist1 = anArtist({
|
||||||
@@ -896,9 +986,45 @@ describe("Navidrome", () => {
|
|||||||
image: NO_IMAGES,
|
image: NO_IMAGES,
|
||||||
};
|
};
|
||||||
|
|
||||||
const tracks = [
|
const tracks = [aTrack({ artist: artistSummary, album: albumSummary })];
|
||||||
aTrack({ artist: artistSummary, album: albumSummary }),
|
|
||||||
];
|
beforeEach(() => {
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(getAlbumXml(artist, album, tracks)))
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should return the album", async () => {
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.tracks(album.id));
|
||||||
|
|
||||||
|
expect(result).toEqual(tracks);
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getAlbum`, {
|
||||||
|
params: {
|
||||||
|
id: album.id,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the album has only no tracks", () => {
|
||||||
|
const album = anAlbum({ id: "album1", name: "Burnin" });
|
||||||
|
|
||||||
|
const artist = anArtist({
|
||||||
|
id: "artist1",
|
||||||
|
name: "Bob Marley",
|
||||||
|
albums: [album],
|
||||||
|
});
|
||||||
|
|
||||||
|
const tracks: Track[] = [];
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
mockGET
|
mockGET
|
||||||
@@ -1184,7 +1310,7 @@ describe("Navidrome", () => {
|
|||||||
.generateToken({ username, password })
|
.generateToken({ username, password })
|
||||||
.then((it) => it as AuthSuccess)
|
.then((it) => it as AuthSuccess)
|
||||||
.then((it) => navidrome.login(it.authToken))
|
.then((it) => navidrome.login(it.authToken))
|
||||||
.then((it) => it.coverArt(coverArtId));
|
.then((it) => it.coverArt(coverArtId, "album"));
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
contentType: streamResponse.headers["content-type"],
|
contentType: streamResponse.headers["content-type"],
|
||||||
@@ -1222,7 +1348,7 @@ describe("Navidrome", () => {
|
|||||||
.generateToken({ username, password })
|
.generateToken({ username, password })
|
||||||
.then((it) => it as AuthSuccess)
|
.then((it) => it as AuthSuccess)
|
||||||
.then((it) => navidrome.login(it.authToken))
|
.then((it) => navidrome.login(it.authToken))
|
||||||
.then((it) => it.coverArt(coverArtId, size));
|
.then((it) => it.coverArt(coverArtId, "album", size));
|
||||||
|
|
||||||
expect(result).toEqual({
|
expect(result).toEqual({
|
||||||
contentType: streamResponse.headers["content-type"],
|
contentType: streamResponse.headers["content-type"],
|
||||||
@@ -1241,5 +1367,566 @@ describe("Navidrome", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("fetching artist art", () => {
|
||||||
|
describe("when no size is specified", () => {
|
||||||
|
describe("when the artist has a valid artist uri", () => {
|
||||||
|
it("should fetch the image from the artist uri", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: "http://example.com/images/small",
|
||||||
|
medium: "http://example.com/images/medium",
|
||||||
|
large: "http://example.com/images/large",
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const artist = anArtist({ id: artistId });
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist"));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
contentType: streamResponse.headers["content-type"],
|
||||||
|
data: streamResponse.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(images.large, {
|
||||||
|
headers: BROWSER_HEADERS,
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the artist doest not have a valid artist uri", () => {
|
||||||
|
describe("however has some albums", () => {
|
||||||
|
it("should fetch the artists first album image", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: undefined,
|
||||||
|
medium: undefined,
|
||||||
|
large: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const album1 = anAlbum();
|
||||||
|
const album2 = anAlbum();
|
||||||
|
|
||||||
|
const artist = anArtist({
|
||||||
|
id: artistId,
|
||||||
|
albums: [album1, album2],
|
||||||
|
});
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist"));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
contentType: streamResponse.headers["content-type"],
|
||||||
|
data: streamResponse.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getCoverArt`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: album1.id,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("and has no albums", () => {
|
||||||
|
it("should return undefined", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: undefined,
|
||||||
|
medium: undefined,
|
||||||
|
large: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const artist = anArtist({ id: artistId, albums: [] });
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist"));
|
||||||
|
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when size is specified", () => {
|
||||||
|
const size = 189;
|
||||||
|
|
||||||
|
describe("when the artist has a valid artist uri", () => {
|
||||||
|
it("should fetch the image from the artist uri and resize it", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: "http://example.com/images/small",
|
||||||
|
medium: "http://example.com/images/medium",
|
||||||
|
large: "http://example.com/images/large",
|
||||||
|
};
|
||||||
|
|
||||||
|
const originalImage = Buffer.from("original image", "ascii");
|
||||||
|
const resizedImage = Buffer.from("resized image", "ascii");
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: originalImage,
|
||||||
|
};
|
||||||
|
|
||||||
|
const artist = anArtist({ id: artistId });
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const resize = jest.fn();
|
||||||
|
(sharp as unknown as jest.Mock).mockReturnValue({ resize });
|
||||||
|
resize.mockReturnValue({ toBuffer: () => Promise.resolve(resizedImage) })
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist", size));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
contentType: streamResponse.headers["content-type"],
|
||||||
|
data: resizedImage,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(images.large, {
|
||||||
|
headers: BROWSER_HEADERS,
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(sharp).toHaveBeenCalledWith(streamResponse.data);
|
||||||
|
expect(resize).toHaveBeenCalledWith(size);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the artist does not have a valid artist uri", () => {
|
||||||
|
describe("however has some albums", () => {
|
||||||
|
it("should fetch the artists first album image", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: undefined,
|
||||||
|
medium: undefined,
|
||||||
|
large: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const album1 = anAlbum({ id: "album1Id" });
|
||||||
|
const album2 = anAlbum({ id: "album2Id" });
|
||||||
|
|
||||||
|
const artist = anArtist({
|
||||||
|
id: artistId,
|
||||||
|
albums: [album1, album2],
|
||||||
|
});
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist", size));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
contentType: streamResponse.headers["content-type"],
|
||||||
|
data: streamResponse.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getCoverArt`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: album1.id,
|
||||||
|
size,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("and has no albums", () => {
|
||||||
|
it("should return undefined", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: undefined,
|
||||||
|
medium: undefined,
|
||||||
|
large: undefined,
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const artist = anArtist({ id: artistId, albums: [] });
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist"));
|
||||||
|
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when the artist has a dodgy looking artist uri", () => {
|
||||||
|
describe("however has some albums", () => {
|
||||||
|
it("should fetch the artists first album image", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: `http://localhost:111/${DODGY_IMAGE_NAME}`,
|
||||||
|
medium: `http://localhost:111/${DODGY_IMAGE_NAME}`,
|
||||||
|
large: `http://localhost:111/${DODGY_IMAGE_NAME}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const album1 = anAlbum({ id: "album1Id" });
|
||||||
|
const album2 = anAlbum({ id: "album2Id" });
|
||||||
|
|
||||||
|
const artist = anArtist({
|
||||||
|
id: artistId,
|
||||||
|
albums: [album1, album2],
|
||||||
|
});
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist", size));
|
||||||
|
|
||||||
|
expect(result).toEqual({
|
||||||
|
contentType: streamResponse.headers["content-type"],
|
||||||
|
data: streamResponse.data,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getCoverArt`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: album1.id,
|
||||||
|
size,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
responseType: "arraybuffer",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("and has no albums", () => {
|
||||||
|
it("should return undefined", async () => {
|
||||||
|
const artistId = "someArtist123";
|
||||||
|
|
||||||
|
const images: Images = {
|
||||||
|
small: `http://localhost:111/${DODGY_IMAGE_NAME}`,
|
||||||
|
medium: `http://localhost:111/${DODGY_IMAGE_NAME}`,
|
||||||
|
large: `http://localhost:111/${DODGY_IMAGE_NAME}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
const streamResponse = {
|
||||||
|
status: 200,
|
||||||
|
headers: {
|
||||||
|
"content-type": "image/jpeg",
|
||||||
|
},
|
||||||
|
data: Buffer.from("the image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
const artist = anArtist({ id: artistId, albums: [] });
|
||||||
|
|
||||||
|
mockGET
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(ok(PING_OK)))
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistXml(artist)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() =>
|
||||||
|
Promise.resolve(ok(artistInfoXml(images)))
|
||||||
|
)
|
||||||
|
.mockImplementationOnce(() => Promise.resolve(streamResponse));
|
||||||
|
|
||||||
|
const result = await navidrome
|
||||||
|
.generateToken({ username, password })
|
||||||
|
.then((it) => it as AuthSuccess)
|
||||||
|
.then((it) => navidrome.login(it.authToken))
|
||||||
|
.then((it) => it.coverArt(artistId, "artist"));
|
||||||
|
|
||||||
|
expect(result).toBeUndefined();
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(`${url}/rest/getArtist`, {
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(axios.get).toHaveBeenCalledWith(
|
||||||
|
`${url}/rest/getArtistInfo`,
|
||||||
|
{
|
||||||
|
params: {
|
||||||
|
id: artistId,
|
||||||
|
...authParams,
|
||||||
|
},
|
||||||
|
headers,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import { InMemoryLinkCodes } from "../src/link_codes";
|
|||||||
describe("server", () => {
|
describe("server", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
jest.clearAllMocks();
|
jest.clearAllMocks();
|
||||||
|
jest.resetAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("/", () => {
|
describe("/", () => {
|
||||||
@@ -448,7 +449,7 @@ describe("server", () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("/album/:albumId/art/size", () => {
|
describe("art", () => {
|
||||||
const musicService = {
|
const musicService = {
|
||||||
login: jest.fn(),
|
login: jest.fn(),
|
||||||
};
|
};
|
||||||
@@ -496,7 +497,64 @@ describe("server", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("when there is a valid access token", () => {
|
describe("when there is a valid access token", () => {
|
||||||
describe("when the image exists in the music service", () => {
|
describe("some invalid art type", () => {
|
||||||
|
it("should return the image and a 200", async () => {
|
||||||
|
const res = await request(server)
|
||||||
|
.get(
|
||||||
|
`/foo/${albumId}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`
|
||||||
|
)
|
||||||
|
.set(BONOB_ACCESS_TOKEN_HEADER, accessToken);
|
||||||
|
|
||||||
|
expect(res.status).toEqual(400);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("artist art", () => {
|
||||||
|
describe("when there is some", () => {
|
||||||
|
it("should return the image and a 200", async () => {
|
||||||
|
const coverArt = {
|
||||||
|
status: 200,
|
||||||
|
contentType: "image/jpeg",
|
||||||
|
data: Buffer.from("some image", "ascii"),
|
||||||
|
};
|
||||||
|
|
||||||
|
musicService.login.mockResolvedValue(musicLibrary);
|
||||||
|
|
||||||
|
musicLibrary.coverArt.mockResolvedValue(coverArt);
|
||||||
|
|
||||||
|
const res = await request(server)
|
||||||
|
.get(
|
||||||
|
`/artist/${albumId}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`
|
||||||
|
)
|
||||||
|
.set(BONOB_ACCESS_TOKEN_HEADER, accessToken);
|
||||||
|
|
||||||
|
expect(res.status).toEqual(coverArt.status);
|
||||||
|
expect(res.header["content-type"]).toEqual(coverArt.contentType);
|
||||||
|
|
||||||
|
expect(musicService.login).toHaveBeenCalledWith(authToken);
|
||||||
|
expect(musicLibrary.coverArt).toHaveBeenCalledWith(albumId, "artist", 180);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when there isn't one", () => {
|
||||||
|
it("should return a 404", async () => {
|
||||||
|
musicService.login.mockResolvedValue(musicLibrary);
|
||||||
|
|
||||||
|
musicLibrary.coverArt.mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
const res = await request(server)
|
||||||
|
.get(
|
||||||
|
`/artist/${albumId}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`
|
||||||
|
)
|
||||||
|
.set(BONOB_ACCESS_TOKEN_HEADER, accessToken);
|
||||||
|
|
||||||
|
expect(res.status).toEqual(404);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("album art", () => {
|
||||||
|
describe("when there is some", () => {
|
||||||
it("should return the image and a 200", async () => {
|
it("should return the image and a 200", async () => {
|
||||||
const coverArt = {
|
const coverArt = {
|
||||||
status: 200,
|
status: 200,
|
||||||
@@ -517,9 +575,26 @@ describe("server", () => {
|
|||||||
expect(res.header["content-type"]).toEqual(coverArt.contentType);
|
expect(res.header["content-type"]).toEqual(coverArt.contentType);
|
||||||
|
|
||||||
expect(musicService.login).toHaveBeenCalledWith(authToken);
|
expect(musicService.login).toHaveBeenCalledWith(authToken);
|
||||||
expect(musicLibrary.coverArt).toHaveBeenCalledWith(albumId, 180);
|
expect(musicLibrary.coverArt).toHaveBeenCalledWith(albumId, "album", 180);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("when there isnt any", () => {
|
||||||
|
it("should return a 404", async () => {
|
||||||
|
musicService.login.mockResolvedValue(musicLibrary);
|
||||||
|
musicLibrary.coverArt.mockResolvedValue(undefined);
|
||||||
|
|
||||||
|
const res = await request(server)
|
||||||
|
.get(
|
||||||
|
`/album/${albumId}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`
|
||||||
|
)
|
||||||
|
.set(BONOB_ACCESS_TOKEN_HEADER, accessToken);
|
||||||
|
|
||||||
|
expect(res.status).toEqual(404);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
SONOS_RECOMMENDED_IMAGE_SIZES,
|
SONOS_RECOMMENDED_IMAGE_SIZES,
|
||||||
track,
|
track,
|
||||||
defaultAlbumArtURI,
|
defaultAlbumArtURI,
|
||||||
|
defaultArtistArtURI,
|
||||||
} from "../src/smapi";
|
} from "../src/smapi";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -175,6 +176,19 @@ describe("defaultAlbumArtURI", () => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("defaultArtistArtURI", () => {
|
||||||
|
it("should create the correct URI", () => {
|
||||||
|
const webAddress = "http://localhost:1234";
|
||||||
|
const accessToken = uuid();
|
||||||
|
const artist = anArtist();
|
||||||
|
|
||||||
|
expect(defaultArtistArtURI(webAddress, accessToken, artist)).toEqual(
|
||||||
|
`${webAddress}/artist/${artist.id}/art/size/180?${BONOB_ACCESS_TOKEN_HEADER}=${accessToken}`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
class Base64AccessTokens implements AccessTokens {
|
class Base64AccessTokens implements AccessTokens {
|
||||||
mint(authToken: string) {
|
mint(authToken: string) {
|
||||||
return Buffer.from(authToken).toString("base64");
|
return Buffer.from(authToken).toString("base64");
|
||||||
@@ -623,7 +637,7 @@ describe("api", () => {
|
|||||||
id: `artist:${it.id}`,
|
id: `artist:${it.id}`,
|
||||||
artistId: it.id,
|
artistId: it.id,
|
||||||
title: it.name,
|
title: it.name,
|
||||||
albumArtURI: it.image.small,
|
albumArtURI: defaultArtistArtURI(rootUrl, accessToken, it),
|
||||||
})),
|
})),
|
||||||
index: 0,
|
index: 0,
|
||||||
total: artists.length,
|
total: artists.length,
|
||||||
@@ -647,7 +661,7 @@ describe("api", () => {
|
|||||||
id: `artist:${it.id}`,
|
id: `artist:${it.id}`,
|
||||||
artistId: it.id,
|
artistId: it.id,
|
||||||
title: it.name,
|
title: it.name,
|
||||||
albumArtURI: it.image.small,
|
albumArtURI: defaultArtistArtURI(rootUrl, accessToken, it),
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
index: 1,
|
index: 1,
|
||||||
|
|||||||
355
yarn.lock
355
yarn.lock
@@ -673,6 +673,13 @@
|
|||||||
"@types/mime" "^1"
|
"@types/mime" "^1"
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/sharp@^0.27.1":
|
||||||
|
version "0.27.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/sharp/-/sharp-0.27.1.tgz#26212ceb191b3de654a898a06577869afc200c57"
|
||||||
|
integrity sha512-RbYmyPjDUzi3lI9Qm68I+82I+DNOe/jW5w+EC1FvpT/f2TYXDG6mmPZQQohy98ufq+u6OB6pQkqpcNMDxzVclg==
|
||||||
|
dependencies:
|
||||||
|
"@types/node" "*"
|
||||||
|
|
||||||
"@types/stack-utils@^2.0.0":
|
"@types/stack-utils@^2.0.0":
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
|
resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.0.tgz#7036640b4e21cc2f259ae826ce843d277dad8cff"
|
||||||
@@ -775,6 +782,16 @@ ansi-escapes@^4.2.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
type-fest "^0.11.0"
|
type-fest "^0.11.0"
|
||||||
|
|
||||||
|
ansi-regex@^2.0.0:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df"
|
||||||
|
integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8=
|
||||||
|
|
||||||
|
ansi-regex@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998"
|
||||||
|
integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=
|
||||||
|
|
||||||
ansi-regex@^4.1.0:
|
ansi-regex@^4.1.0:
|
||||||
version "4.1.0"
|
version "4.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997"
|
||||||
@@ -815,6 +832,19 @@ anymatch@^3.0.3, anymatch@~3.1.1:
|
|||||||
normalize-path "^3.0.0"
|
normalize-path "^3.0.0"
|
||||||
picomatch "^2.0.4"
|
picomatch "^2.0.4"
|
||||||
|
|
||||||
|
aproba@^1.0.3:
|
||||||
|
version "1.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a"
|
||||||
|
integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==
|
||||||
|
|
||||||
|
are-we-there-yet@~1.1.2:
|
||||||
|
version "1.1.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21"
|
||||||
|
integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==
|
||||||
|
dependencies:
|
||||||
|
delegates "^1.0.0"
|
||||||
|
readable-stream "^2.0.6"
|
||||||
|
|
||||||
arg@^4.1.0:
|
arg@^4.1.0:
|
||||||
version "4.1.3"
|
version "4.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
|
||||||
@@ -847,6 +877,11 @@ array-flatten@1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2"
|
||||||
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
|
integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=
|
||||||
|
|
||||||
|
array-flatten@^3.0.0:
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-3.0.0.tgz#6428ca2ee52c7b823192ec600fa3ed2f157cd541"
|
||||||
|
integrity sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==
|
||||||
|
|
||||||
array-unique@^0.3.2:
|
array-unique@^0.3.2:
|
||||||
version "0.3.2"
|
version "0.3.2"
|
||||||
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
|
||||||
@@ -972,6 +1007,11 @@ balanced-match@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767"
|
||||||
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c=
|
||||||
|
|
||||||
|
base64-js@^1.3.1:
|
||||||
|
version "1.5.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
|
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||||
|
|
||||||
base@^0.11.1:
|
base@^0.11.1:
|
||||||
version "0.11.2"
|
version "0.11.2"
|
||||||
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f"
|
||||||
@@ -1004,6 +1044,15 @@ binary-extensions@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||||
|
|
||||||
|
bl@^4.0.3:
|
||||||
|
version "4.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a"
|
||||||
|
integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==
|
||||||
|
dependencies:
|
||||||
|
buffer "^5.5.0"
|
||||||
|
inherits "^2.0.4"
|
||||||
|
readable-stream "^3.4.0"
|
||||||
|
|
||||||
body-parser@1.19.0:
|
body-parser@1.19.0:
|
||||||
version "1.19.0"
|
version "1.19.0"
|
||||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a"
|
||||||
@@ -1089,6 +1138,14 @@ buffer-from@1.x, buffer-from@^1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef"
|
||||||
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==
|
||||||
|
|
||||||
|
buffer@^5.5.0:
|
||||||
|
version "5.7.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
|
||||||
|
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
|
||||||
|
dependencies:
|
||||||
|
base64-js "^1.3.1"
|
||||||
|
ieee754 "^1.1.13"
|
||||||
|
|
||||||
bytes@3.1.0:
|
bytes@3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6"
|
||||||
@@ -1211,6 +1268,11 @@ chokidar@^3.2.2:
|
|||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
fsevents "~2.3.1"
|
fsevents "~2.3.1"
|
||||||
|
|
||||||
|
chownr@^1.1.1:
|
||||||
|
version "1.1.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b"
|
||||||
|
integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==
|
||||||
|
|
||||||
ci-info@^2.0.0:
|
ci-info@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-2.0.0.tgz#67a9e964be31a51e15e5010d58e6f12834002f46"
|
||||||
@@ -1257,6 +1319,11 @@ co@^4.6.0:
|
|||||||
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
|
||||||
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
|
integrity sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=
|
||||||
|
|
||||||
|
code-point-at@^1.0.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77"
|
||||||
|
integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=
|
||||||
|
|
||||||
collect-v8-coverage@^1.0.0:
|
collect-v8-coverage@^1.0.0:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
|
resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.1.tgz#cc2c8e94fc18bbdffe64d6534570c8a673b27f59"
|
||||||
@@ -1302,6 +1369,14 @@ color-string@^1.5.2:
|
|||||||
color-name "^1.0.0"
|
color-name "^1.0.0"
|
||||||
simple-swizzle "^0.2.2"
|
simple-swizzle "^0.2.2"
|
||||||
|
|
||||||
|
color-string@^1.5.4:
|
||||||
|
version "1.5.5"
|
||||||
|
resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.5.tgz#65474a8f0e7439625f3d27a6a19d89fc45223014"
|
||||||
|
integrity sha512-jgIoum0OfQfq9Whcfc2z/VhCNcmQjWbey6qBX0vqt7YICflUmBCh9E9CiQD5GSJ+Uehixm3NUwHVhqUAWRivZg==
|
||||||
|
dependencies:
|
||||||
|
color-name "^1.0.0"
|
||||||
|
simple-swizzle "^0.2.2"
|
||||||
|
|
||||||
color@3.0.x:
|
color@3.0.x:
|
||||||
version "3.0.0"
|
version "3.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
|
resolved "https://registry.yarnpkg.com/color/-/color-3.0.0.tgz#d920b4328d534a3ac8295d68f7bd4ba6c427be9a"
|
||||||
@@ -1310,6 +1385,14 @@ color@3.0.x:
|
|||||||
color-convert "^1.9.1"
|
color-convert "^1.9.1"
|
||||||
color-string "^1.5.2"
|
color-string "^1.5.2"
|
||||||
|
|
||||||
|
color@^3.1.3:
|
||||||
|
version "3.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/color/-/color-3.1.3.tgz#ca67fb4e7b97d611dcde39eceed422067d91596e"
|
||||||
|
integrity sha512-xgXAcTHa2HeFCGLE9Xs/R82hujGtu9Jd9x4NW3T34+OMs7VoPsjwzRczKHvTAHeJwWFwX5j15+MgAppE8ztObQ==
|
||||||
|
dependencies:
|
||||||
|
color-convert "^1.9.1"
|
||||||
|
color-string "^1.5.4"
|
||||||
|
|
||||||
colors@^1.2.1:
|
colors@^1.2.1:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78"
|
||||||
@@ -1352,6 +1435,11 @@ configstore@^5.0.1:
|
|||||||
write-file-atomic "^3.0.0"
|
write-file-atomic "^3.0.0"
|
||||||
xdg-basedir "^4.0.0"
|
xdg-basedir "^4.0.0"
|
||||||
|
|
||||||
|
console-control-strings@^1.0.0, console-control-strings@~1.1.0:
|
||||||
|
version "1.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e"
|
||||||
|
integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=
|
||||||
|
|
||||||
content-disposition@0.5.3:
|
content-disposition@0.5.3:
|
||||||
version "0.5.3"
|
version "0.5.3"
|
||||||
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd"
|
||||||
@@ -1514,6 +1602,20 @@ decompress-response@^3.3.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
mimic-response "^1.0.0"
|
mimic-response "^1.0.0"
|
||||||
|
|
||||||
|
decompress-response@^4.2.0:
|
||||||
|
version "4.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-4.2.1.tgz#414023cc7a302da25ce2ec82d0d5238ccafd8986"
|
||||||
|
integrity sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==
|
||||||
|
dependencies:
|
||||||
|
mimic-response "^2.0.0"
|
||||||
|
|
||||||
|
decompress-response@^6.0.0:
|
||||||
|
version "6.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc"
|
||||||
|
integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==
|
||||||
|
dependencies:
|
||||||
|
mimic-response "^3.1.0"
|
||||||
|
|
||||||
deep-eql@^3.0.1:
|
deep-eql@^3.0.1:
|
||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
|
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df"
|
||||||
@@ -1568,6 +1670,11 @@ delayed-stream@~1.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
|
||||||
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
|
||||||
|
|
||||||
|
delegates@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a"
|
||||||
|
integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=
|
||||||
|
|
||||||
depd@~1.1.2:
|
depd@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9"
|
||||||
@@ -1583,6 +1690,11 @@ destroy@~1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80"
|
||||||
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=
|
||||||
|
|
||||||
|
detect-libc@^1.0.3:
|
||||||
|
version "1.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b"
|
||||||
|
integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=
|
||||||
|
|
||||||
detect-newline@^3.0.0:
|
detect-newline@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
resolved "https://registry.yarnpkg.com/detect-newline/-/detect-newline-3.1.0.tgz#576f5dfc63ae1a192ff192d8ad3af6308991b651"
|
||||||
@@ -1655,7 +1767,7 @@ encodeurl@~1.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||||
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=
|
||||||
|
|
||||||
end-of-stream@^1.1.0:
|
end-of-stream@^1.1.0, end-of-stream@^1.4.1:
|
||||||
version "1.4.4"
|
version "1.4.4"
|
||||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0"
|
||||||
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==
|
||||||
@@ -1777,6 +1889,11 @@ expand-brackets@^2.1.4:
|
|||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
|
expand-template@^2.0.3:
|
||||||
|
version "2.0.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
|
||||||
|
integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==
|
||||||
|
|
||||||
expect@^26.6.2:
|
expect@^26.6.2:
|
||||||
version "26.6.2"
|
version "26.6.2"
|
||||||
resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417"
|
resolved "https://registry.yarnpkg.com/expect/-/expect-26.6.2.tgz#c6b996bf26bf3fe18b67b2d0f51fc981ba934417"
|
||||||
@@ -2009,6 +2126,11 @@ fresh@0.5.2:
|
|||||||
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7"
|
||||||
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=
|
||||||
|
|
||||||
|
fs-constants@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad"
|
||||||
|
integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==
|
||||||
|
|
||||||
fs.realpath@^1.0.0:
|
fs.realpath@^1.0.0:
|
||||||
version "1.0.0"
|
version "1.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
|
||||||
@@ -2024,6 +2146,20 @@ function-bind@^1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||||
|
|
||||||
|
gauge@~2.7.3:
|
||||||
|
version "2.7.4"
|
||||||
|
resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7"
|
||||||
|
integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=
|
||||||
|
dependencies:
|
||||||
|
aproba "^1.0.3"
|
||||||
|
console-control-strings "^1.0.0"
|
||||||
|
has-unicode "^2.0.0"
|
||||||
|
object-assign "^4.1.0"
|
||||||
|
signal-exit "^3.0.0"
|
||||||
|
string-width "^1.0.1"
|
||||||
|
strip-ansi "^3.0.1"
|
||||||
|
wide-align "^1.1.0"
|
||||||
|
|
||||||
gensync@^1.0.0-beta.1:
|
gensync@^1.0.0-beta.1:
|
||||||
version "1.0.0-beta.2"
|
version "1.0.0-beta.2"
|
||||||
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0"
|
||||||
@@ -2080,6 +2216,11 @@ getpass@^0.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
github-from-package@0.0.0:
|
||||||
|
version "0.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
|
||||||
|
integrity sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=
|
||||||
|
|
||||||
glob-parent@~5.1.0:
|
glob-parent@~5.1.0:
|
||||||
version "5.1.1"
|
version "5.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229"
|
||||||
@@ -2166,6 +2307,11 @@ has-flag@^4.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||||
|
|
||||||
|
has-unicode@^2.0.0:
|
||||||
|
version "2.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9"
|
||||||
|
integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=
|
||||||
|
|
||||||
has-value@^0.3.1:
|
has-value@^0.3.1:
|
||||||
version "0.3.1"
|
version "0.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f"
|
||||||
@@ -2297,6 +2443,11 @@ iconv-lite@0.4.24:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3"
|
safer-buffer ">= 2.1.2 < 3"
|
||||||
|
|
||||||
|
ieee754@^1.1.13:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
|
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||||
|
|
||||||
ignore-by-default@^1.0.1:
|
ignore-by-default@^1.0.1:
|
||||||
version "1.0.1"
|
version "1.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
|
||||||
@@ -2328,7 +2479,7 @@ inflight@^1.0.4:
|
|||||||
once "^1.3.0"
|
once "^1.3.0"
|
||||||
wrappy "1"
|
wrappy "1"
|
||||||
|
|
||||||
inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@~2.0.3:
|
inherits@2, inherits@2.0.4, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3:
|
||||||
version "2.0.4"
|
version "2.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
|
||||||
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
|
||||||
@@ -2462,6 +2613,13 @@ is-extglob@^2.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2"
|
||||||
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=
|
||||||
|
|
||||||
|
is-fullwidth-code-point@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb"
|
||||||
|
integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs=
|
||||||
|
dependencies:
|
||||||
|
number-is-nan "^1.0.0"
|
||||||
|
|
||||||
is-fullwidth-code-point@^2.0.0:
|
is-fullwidth-code-point@^2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f"
|
||||||
@@ -3322,6 +3480,16 @@ mimic-response@^1.0.0, mimic-response@^1.0.1:
|
|||||||
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
|
||||||
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
|
integrity sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==
|
||||||
|
|
||||||
|
mimic-response@^2.0.0:
|
||||||
|
version "2.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-2.1.0.tgz#d13763d35f613d09ec37ebb30bac0469c0ee8f43"
|
||||||
|
integrity sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==
|
||||||
|
|
||||||
|
mimic-response@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9"
|
||||||
|
integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==
|
||||||
|
|
||||||
minimatch@^3.0.4:
|
minimatch@^3.0.4:
|
||||||
version "3.0.4"
|
version "3.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||||
@@ -3329,7 +3497,7 @@ minimatch@^3.0.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion "^1.1.7"
|
brace-expansion "^1.1.7"
|
||||||
|
|
||||||
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.5:
|
minimist@^1.1.1, minimist@^1.2.0, minimist@^1.2.3, minimist@^1.2.5:
|
||||||
version "1.2.5"
|
version "1.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
|
||||||
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
|
||||||
@@ -3342,6 +3510,11 @@ mixin-deep@^1.2.0:
|
|||||||
for-in "^1.0.2"
|
for-in "^1.0.2"
|
||||||
is-extendable "^1.0.1"
|
is-extendable "^1.0.1"
|
||||||
|
|
||||||
|
mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
|
||||||
|
version "0.5.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
|
||||||
|
integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==
|
||||||
|
|
||||||
mkdirp@1.x:
|
mkdirp@1.x:
|
||||||
version "1.0.4"
|
version "1.0.4"
|
||||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||||
@@ -3395,6 +3568,11 @@ nanomatch@^1.2.9:
|
|||||||
snapdragon "^0.8.1"
|
snapdragon "^0.8.1"
|
||||||
to-regex "^3.0.1"
|
to-regex "^3.0.1"
|
||||||
|
|
||||||
|
napi-build-utils@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-1.0.2.tgz#b1fddc0b2c46e380a0b7a76f984dd47c41a13806"
|
||||||
|
integrity sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==
|
||||||
|
|
||||||
natural-compare@^1.4.0:
|
natural-compare@^1.4.0:
|
||||||
version "1.4.0"
|
version "1.4.0"
|
||||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||||
@@ -3410,6 +3588,18 @@ nice-try@^1.0.4:
|
|||||||
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366"
|
||||||
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==
|
||||||
|
|
||||||
|
node-abi@^2.7.0:
|
||||||
|
version "2.21.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.21.0.tgz#c2dc9ebad6f4f53d6ea9b531e7b8faad81041d48"
|
||||||
|
integrity sha512-smhrivuPqEM3H5LmnY3KU6HfYv0u4QklgAxfFyRNujKUzbUcYZ+Jc2EhukB9SRcD2VpqhxM7n/MIcp1Ua1/JMg==
|
||||||
|
dependencies:
|
||||||
|
semver "^5.4.1"
|
||||||
|
|
||||||
|
node-addon-api@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.1.0.tgz#98b21931557466c6729e51cb77cd39c965f42239"
|
||||||
|
integrity sha512-flmrDNB06LIl5lywUz7YlNGZH/5p0M7W28k8hzd9Lshtdh1wshD2Y+U4h9LD6KObOy1f+fEVdgprPrEymjM5uw==
|
||||||
|
|
||||||
node-fetch@^2.6.1:
|
node-fetch@^2.6.1:
|
||||||
version "2.6.1"
|
version "2.6.1"
|
||||||
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.1.tgz#045bd323631f76ed2e2b55573394416b639a0052"
|
||||||
@@ -3460,6 +3650,11 @@ nodemon@^2.0.7:
|
|||||||
undefsafe "^2.0.3"
|
undefsafe "^2.0.3"
|
||||||
update-notifier "^4.1.0"
|
update-notifier "^4.1.0"
|
||||||
|
|
||||||
|
noop-logger@^0.1.1:
|
||||||
|
version "0.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/noop-logger/-/noop-logger-0.1.1.tgz#94a2b1633c4f1317553007d8966fd0e841b6a4c2"
|
||||||
|
integrity sha1-lKKxYzxPExdVMAfYlm/Q6EG2pMI=
|
||||||
|
|
||||||
nopt@~1.0.10:
|
nopt@~1.0.10:
|
||||||
version "1.0.10"
|
version "1.0.10"
|
||||||
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
|
||||||
@@ -3508,6 +3703,21 @@ npm-run-path@^4.0.0:
|
|||||||
dependencies:
|
dependencies:
|
||||||
path-key "^3.0.0"
|
path-key "^3.0.0"
|
||||||
|
|
||||||
|
npmlog@^4.0.1, npmlog@^4.1.2:
|
||||||
|
version "4.1.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b"
|
||||||
|
integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==
|
||||||
|
dependencies:
|
||||||
|
are-we-there-yet "~1.1.2"
|
||||||
|
console-control-strings "~1.1.0"
|
||||||
|
gauge "~2.7.3"
|
||||||
|
set-blocking "~2.0.0"
|
||||||
|
|
||||||
|
number-is-nan@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d"
|
||||||
|
integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=
|
||||||
|
|
||||||
nwsapi@^2.2.0:
|
nwsapi@^2.2.0:
|
||||||
version "2.2.0"
|
version "2.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.0.tgz#204879a9e3d068ff2a55139c2c772780681a38b7"
|
||||||
@@ -3518,6 +3728,11 @@ oauth-sign@~0.9.0:
|
|||||||
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
|
||||||
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
|
||||||
|
|
||||||
|
object-assign@^4.1.0:
|
||||||
|
version "4.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
|
||||||
|
integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=
|
||||||
|
|
||||||
object-copy@^0.1.0:
|
object-copy@^0.1.0:
|
||||||
version "0.1.0"
|
version "0.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
|
resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c"
|
||||||
@@ -3719,6 +3934,27 @@ posix-character-classes@^0.1.0:
|
|||||||
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab"
|
||||||
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
|
integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=
|
||||||
|
|
||||||
|
prebuild-install@^6.0.1:
|
||||||
|
version "6.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-6.0.1.tgz#5902172f7a40eb67305b96c2a695db32636ee26d"
|
||||||
|
integrity sha512-7GOJrLuow8yeiyv75rmvZyeMGzl8mdEX5gY69d6a6bHWmiPevwqFw+tQavhK0EYMaSg3/KD24cWqeQv1EWsqDQ==
|
||||||
|
dependencies:
|
||||||
|
detect-libc "^1.0.3"
|
||||||
|
expand-template "^2.0.3"
|
||||||
|
github-from-package "0.0.0"
|
||||||
|
minimist "^1.2.3"
|
||||||
|
mkdirp-classic "^0.5.3"
|
||||||
|
napi-build-utils "^1.0.1"
|
||||||
|
node-abi "^2.7.0"
|
||||||
|
noop-logger "^0.1.1"
|
||||||
|
npmlog "^4.0.1"
|
||||||
|
pump "^3.0.0"
|
||||||
|
rc "^1.2.7"
|
||||||
|
simple-get "^3.0.3"
|
||||||
|
tar-fs "^2.0.0"
|
||||||
|
tunnel-agent "^0.6.0"
|
||||||
|
which-pm-runs "^1.0.0"
|
||||||
|
|
||||||
prelude-ls@~1.1.2:
|
prelude-ls@~1.1.2:
|
||||||
version "1.1.2"
|
version "1.1.2"
|
||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||||
@@ -3820,7 +4056,7 @@ raw-body@2.4.0:
|
|||||||
iconv-lite "0.4.24"
|
iconv-lite "0.4.24"
|
||||||
unpipe "1.0.0"
|
unpipe "1.0.0"
|
||||||
|
|
||||||
rc@^1.2.8:
|
rc@^1.2.7, rc@^1.2.8:
|
||||||
version "1.2.8"
|
version "1.2.8"
|
||||||
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed"
|
||||||
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
|
integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==
|
||||||
@@ -3854,7 +4090,7 @@ read-pkg@^5.2.0:
|
|||||||
parse-json "^5.0.0"
|
parse-json "^5.0.0"
|
||||||
type-fest "^0.6.0"
|
type-fest "^0.6.0"
|
||||||
|
|
||||||
readable-stream@^2.3.7:
|
readable-stream@^2.0.6, readable-stream@^2.3.7:
|
||||||
version "2.3.7"
|
version "2.3.7"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57"
|
||||||
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==
|
||||||
@@ -3867,7 +4103,7 @@ readable-stream@^2.3.7:
|
|||||||
string_decoder "~1.1.1"
|
string_decoder "~1.1.1"
|
||||||
util-deprecate "~1.0.1"
|
util-deprecate "~1.0.1"
|
||||||
|
|
||||||
readable-stream@^3.4.0, readable-stream@^3.6.0:
|
readable-stream@^3.1.1, readable-stream@^3.4.0, readable-stream@^3.6.0:
|
||||||
version "3.6.0"
|
version "3.6.0"
|
||||||
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198"
|
||||||
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==
|
||||||
@@ -4082,7 +4318,7 @@ semver-diff@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7"
|
||||||
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==
|
||||||
|
|
||||||
semver@7.x, semver@^7.3.2:
|
semver@7.x, semver@^7.3.2, semver@^7.3.4:
|
||||||
version "7.3.4"
|
version "7.3.4"
|
||||||
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
|
resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.4.tgz#27aaa7d2e4ca76452f98d3add093a72c943edc97"
|
||||||
integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
|
integrity sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==
|
||||||
@@ -4123,7 +4359,7 @@ serve-static@1.14.1:
|
|||||||
parseurl "~1.3.3"
|
parseurl "~1.3.3"
|
||||||
send "0.17.1"
|
send "0.17.1"
|
||||||
|
|
||||||
set-blocking@^2.0.0:
|
set-blocking@^2.0.0, set-blocking@~2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7"
|
||||||
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc=
|
||||||
@@ -4143,6 +4379,22 @@ setprototypeof@1.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
|
resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683"
|
||||||
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
|
integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==
|
||||||
|
|
||||||
|
sharp@^0.27.2:
|
||||||
|
version "0.27.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/sharp/-/sharp-0.27.2.tgz#a939775e630e88600c0b5e68f20593aea722252f"
|
||||||
|
integrity sha512-w3FVoONPG/x5MXCc3wsjOS+b9h3CI60qkus6EPQU4dkT0BDm0PyGhDCK6KhtfT3/vbeOMOXAKFNSw+I3QGWkMA==
|
||||||
|
dependencies:
|
||||||
|
array-flatten "^3.0.0"
|
||||||
|
color "^3.1.3"
|
||||||
|
detect-libc "^1.0.3"
|
||||||
|
node-addon-api "^3.1.0"
|
||||||
|
npmlog "^4.1.2"
|
||||||
|
prebuild-install "^6.0.1"
|
||||||
|
semver "^7.3.4"
|
||||||
|
simple-get "^4.0.0"
|
||||||
|
tar-fs "^2.1.1"
|
||||||
|
tunnel-agent "^0.6.0"
|
||||||
|
|
||||||
shebang-command@^1.2.0:
|
shebang-command@^1.2.0:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea"
|
||||||
@@ -4177,6 +4429,29 @@ signal-exit@^3.0.0, signal-exit@^3.0.2:
|
|||||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c"
|
||||||
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==
|
||||||
|
|
||||||
|
simple-concat@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f"
|
||||||
|
integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==
|
||||||
|
|
||||||
|
simple-get@^3.0.3:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-3.1.0.tgz#b45be062435e50d159540b576202ceec40b9c6b3"
|
||||||
|
integrity sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==
|
||||||
|
dependencies:
|
||||||
|
decompress-response "^4.2.0"
|
||||||
|
once "^1.3.1"
|
||||||
|
simple-concat "^1.0.0"
|
||||||
|
|
||||||
|
simple-get@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.0.tgz#73fa628278d21de83dadd5512d2cc1f4872bd675"
|
||||||
|
integrity sha512-ZalZGexYr3TA0SwySsr5HlgOOinS4Jsa8YB2GJ6lUNAazyAu4KG/VmzMTwAt2YVXzzVj8QmefmAonZIK2BSGcQ==
|
||||||
|
dependencies:
|
||||||
|
decompress-response "^6.0.0"
|
||||||
|
once "^1.3.1"
|
||||||
|
simple-concat "^1.0.0"
|
||||||
|
|
||||||
simple-swizzle@^0.2.2:
|
simple-swizzle@^0.2.2:
|
||||||
version "0.2.2"
|
version "0.2.2"
|
||||||
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
|
resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a"
|
||||||
@@ -4374,6 +4649,23 @@ string-length@^4.0.1:
|
|||||||
char-regex "^1.0.2"
|
char-regex "^1.0.2"
|
||||||
strip-ansi "^6.0.0"
|
strip-ansi "^6.0.0"
|
||||||
|
|
||||||
|
string-width@^1.0.1:
|
||||||
|
version "1.0.2"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3"
|
||||||
|
integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=
|
||||||
|
dependencies:
|
||||||
|
code-point-at "^1.0.0"
|
||||||
|
is-fullwidth-code-point "^1.0.0"
|
||||||
|
strip-ansi "^3.0.0"
|
||||||
|
|
||||||
|
"string-width@^1.0.2 || 2":
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e"
|
||||||
|
integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==
|
||||||
|
dependencies:
|
||||||
|
is-fullwidth-code-point "^2.0.0"
|
||||||
|
strip-ansi "^4.0.0"
|
||||||
|
|
||||||
string-width@^3.0.0:
|
string-width@^3.0.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
|
||||||
@@ -4406,6 +4698,20 @@ string_decoder@~1.1.1:
|
|||||||
dependencies:
|
dependencies:
|
||||||
safe-buffer "~5.1.0"
|
safe-buffer "~5.1.0"
|
||||||
|
|
||||||
|
strip-ansi@^3.0.0, strip-ansi@^3.0.1:
|
||||||
|
version "3.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf"
|
||||||
|
integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^2.0.0"
|
||||||
|
|
||||||
|
strip-ansi@^4.0.0:
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f"
|
||||||
|
integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8=
|
||||||
|
dependencies:
|
||||||
|
ansi-regex "^3.0.0"
|
||||||
|
|
||||||
strip-ansi@^5.1.0:
|
strip-ansi@^5.1.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
|
||||||
@@ -4497,6 +4803,27 @@ symbol-tree@^3.2.4:
|
|||||||
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
|
||||||
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
|
||||||
|
|
||||||
|
tar-fs@^2.0.0, tar-fs@^2.1.1:
|
||||||
|
version "2.1.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.1.tgz#489a15ab85f1f0befabb370b7de4f9eb5cbe8784"
|
||||||
|
integrity sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==
|
||||||
|
dependencies:
|
||||||
|
chownr "^1.1.1"
|
||||||
|
mkdirp-classic "^0.5.2"
|
||||||
|
pump "^3.0.0"
|
||||||
|
tar-stream "^2.1.4"
|
||||||
|
|
||||||
|
tar-stream@^2.1.4:
|
||||||
|
version "2.2.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287"
|
||||||
|
integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==
|
||||||
|
dependencies:
|
||||||
|
bl "^4.0.3"
|
||||||
|
end-of-stream "^1.4.1"
|
||||||
|
fs-constants "^1.0.0"
|
||||||
|
inherits "^2.0.3"
|
||||||
|
readable-stream "^3.1.1"
|
||||||
|
|
||||||
term-size@^2.1.0:
|
term-size@^2.1.0:
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
|
resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54"
|
||||||
@@ -4915,6 +5242,11 @@ which-module@^2.0.0:
|
|||||||
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
|
||||||
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=
|
||||||
|
|
||||||
|
which-pm-runs@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/which-pm-runs/-/which-pm-runs-1.0.0.tgz#670b3afbc552e0b55df6b7780ca74615f23ad1cb"
|
||||||
|
integrity sha1-Zws6+8VS4LVd9rd4DKdGFfI60cs=
|
||||||
|
|
||||||
which@^1.2.9:
|
which@^1.2.9:
|
||||||
version "1.3.1"
|
version "1.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
|
||||||
@@ -4929,6 +5261,13 @@ which@^2.0.1, which@^2.0.2:
|
|||||||
dependencies:
|
dependencies:
|
||||||
isexe "^2.0.0"
|
isexe "^2.0.0"
|
||||||
|
|
||||||
|
wide-align@^1.1.0:
|
||||||
|
version "1.1.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457"
|
||||||
|
integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==
|
||||||
|
dependencies:
|
||||||
|
string-width "^1.0.2 || 2"
|
||||||
|
|
||||||
widest-line@^3.1.0:
|
widest-line@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
|
resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca"
|
||||||
|
|||||||
Reference in New Issue
Block a user