diff --git a/src/main/webui/.eslintignore b/src/main/webui/.eslintignore
index 55af28b..35c3afb 100644
--- a/src/main/webui/.eslintignore
+++ b/src/main/webui/.eslintignore
@@ -1,5 +1,6 @@
**/*.css
**/*.json
**/*.ico
+**/*.bak
**/index.html
**/README.md
diff --git a/src/main/webui/package.json b/src/main/webui/package.json
index f46df2e..82feadc 100644
--- a/src/main/webui/package.json
+++ b/src/main/webui/package.json
@@ -72,7 +72,7 @@
"dev": "webpack-dev-server --open --hot",
"lint": "eslint './src/**'",
"lint-fix": "eslint './src/**' --fix",
- "server": "npm run build-dev && nodemon src/server/app.js --exec babel-node --presets @babel/preset-env",
+ "server": "nodemon src/server/app.js --exec babel-node --presets @babel/preset-env",
"test": "NODE_ENV=test jest"
}
}
diff --git a/src/main/webui/src/app/components/content/Main.jsx b/src/main/webui/src/app/components/content/Main.jsx
index 80e30fe..d68fec5 100644
--- a/src/main/webui/src/app/components/content/Main.jsx
+++ b/src/main/webui/src/app/components/content/Main.jsx
@@ -63,8 +63,6 @@ export const Main = () =>
} />
{
//
- //
- //
}
;
diff --git a/src/main/webui/src/app/components/content/addons/Cache.jsx b/src/main/webui/src/app/components/content/addons/Cache.jsx
index 89efbae..9adfa67 100644
--- a/src/main/webui/src/app/components/content/addons/Cache.jsx
+++ b/src/main/webui/src/app/components/content/addons/Cache.jsx
@@ -63,7 +63,7 @@ export default function Cache() {
Input the the metadata url:
(Can be a full or a relative url like "/api/content/maven/group/central/org/foo/bar/maven-metadata.xml. Be noticed that this will trigger the deletions of the target path from all affected groups .")
- {errors.path?.type === "required" && Metadata url is required }
+ {errors.path?.type === "required" && Metadata url is required }
Delete
diff --git a/src/main/webui/src/app/components/content/addons/NFC.jsx b/src/main/webui/src/app/components/content/addons/NFC.jsx
index 68b7653..8c226ce 100644
--- a/src/main/webui/src/app/components/content/addons/NFC.jsx
+++ b/src/main/webui/src/app/components/content/addons/NFC.jsx
@@ -14,8 +14,326 @@
* limitations under the License.
*/
-import React from 'react';
+import React, {useState, useEffect, useRef, Fragment} from 'react';
+import {LoadingSpiner} from '../common/LoadingSpiner.jsx';
+import {IndyRest} from '#utils/RestClient.js';
+import {Utils} from '#utils/AppUtils.js';
+
+const {storeQueryRes, nfcRes} = IndyRest;
export default function NFC() {
- return
This is not implemented yet!
;
+ const [nfcStoreKeys, setNfcStoreKeys] = useState([]);
+ const [message, setMessage] = useState('');
+ const [error, setError] = useState('');
+ const [currentKey, setCurrentKey] = useState("");
+ const [sections, setSections] = useState([]);
+ const pageSizes = [10, 50, 100];
+ const page = useRef({
+ index: 0,
+ size: pageSizes[0]
+ });
+ const [prevDisabled, setPrevDisabled] = useState(true);
+ const [paginationHidden, setPagginationHidden] = useState(true);
+ const [isShowAll, setShowAll] = useState(true);
+ const [loading, setLoading] = useState(false);
+ const [loadingSection, setLoadingSection] = useState(false);
+
+ const updatePage = partialPage => {
+ const newPage = Utils.cloneObj(page.current);
+ for (let key in partialPage) {
+ if (Object.hasOwn(partialPage, key)){
+ newPage[key] = partialPage[key];
+ }
+ }
+ page.current = newPage;
+ };
+ useEffect(()=>{
+ setLoadingSection(true);
+ (async () =>{
+ const res = await storeQueryRes.getEndpoints("all");
+ if (res.success){
+ const raw = await res.result;
+ const allKeys = raw.items.filter(item=>item.type!=="group").map(item=>item.key);
+ setNfcStoreKeys(allKeys);
+ setLoadingSection(false);
+ }else{
+ setError(res.error.message);
+ }
+ })();
+ }, []);
+
+ const clearMessage = () => {
+ setMessage('');
+ setError('');
+ };
+
+ const labelSections = secs => {
+ secs.forEach(s => {
+ s.label = Utils.keyLabel(s.key);
+ s.paths.sort();
+ });
+ };
+
+ const showSection = e => {
+ const selectKey = e.target.value;
+ if (!selectKey){
+ return;
+ }
+ clearMessage();
+ setCurrentKey(selectKey);
+ setPagginationHidden(true);
+ setLoading(true);
+ const [packageType, type, name] = selectKey.split(':');
+ setSections([]);
+ (async ()=> {
+ const resp = await nfcRes.get(packageType, type, name, "");
+ if(resp.success){
+ if(resp.result && resp.result.sections !== undefined){
+ labelSections(resp.result.sections);
+ setSections(Utils.sortByEmbeddedKey(resp.result.sections));
+ setShowAll(false);
+ }
+ }
+ setLoading(false);
+ })();
+ };
+
+ const showAll = e => {
+ e.preventDefault();
+ clearMessage();
+ const [index, size] = [page.current.index, page.current.size];
+ setPagginationHidden(false);
+ setLoading(true);
+ setSections([]);
+ (async ()=> {
+ const resp = await nfcRes.query(index, size);
+ if(resp.success){
+ if(resp.result && resp.result.sections !== undefined){
+ labelSections(resp.result.sections);
+ setSections(Utils.sortByEmbeddedKey(resp.result.sections));
+ setShowAll(true);
+ setCurrentKey("");
+ }
+ }
+ setLoading(false);
+ })();
+ };
+
+ const clearAllNFC = e => {
+ e.preventDefault();
+ (async () => {
+ const result = await nfcRes.deleteAll();
+ if(result.success){
+ setSections([]);
+ setPagginationHidden(true);
+ setMessage("All NFC entries cleared successfully.");
+ }else{
+ Utils.logMessage(`Failed to clear all NFC! Error reason: ${result.error.message}`);
+ }
+ })();
+ };
+
+ const clearSection = (section, secs) => {
+ setMessage("");
+ let key = section.key;
+ // alert( "Clear all NFC entries for: " + key );
+
+ let name = Utils.nameFromKey(key);
+ let packageType = Utils.packageTypeFromKey(key);
+ let type = Utils.typeFromKey(key);
+ (async () => {
+ const result = await nfcRes.delete(packageType, type, name, "");
+ if(result.success){
+ setMessage(`Cleared NFC for ${key}`);
+ section.paths = [];
+ const index = secs.indexOf(section);
+ secs.splice(index, 1);
+ }else{
+ setMessage(`Failed to clear NFC for ${key}`);
+ setError(result.error);
+ }
+ })();
+ };
+
+ const clearSectionPath = (section, path) => {
+ const subPath = path.substring(1);
+ let key = section.key;
+
+ // alert( "Clear all NFC entries for: " + key + ", path: " + path );
+
+ let name = Utils.nameFromKey(key);
+ let packageType = Utils.packageTypeFromKey(key);
+ let type = Utils.typeFromKey(key);
+
+ (async () => {
+ const result = await nfcRes.delete(packageType, type, name, subPath);
+ if(result.success){
+ setMessage(`Cleared NFC for ${key}, path: ${subPath}`);
+ let idx = section.paths.indexOf(subPath);
+ section.paths.splice(idx,1);
+ }else{
+ setError(result.error);
+ }
+ })();
+ };
+
+ const queryByPageIndexAndSize = (index, size) =>{
+ setMessage("");
+ setPagginationHidden(true);
+ setLoading(true);
+ setSections([]);
+ if (isShowAll){
+ // alert( "showing all NFC entries");
+ // delete $scope.currentKey;
+ (async () => {
+ const resp = await nfcRes.query(index, size);
+ if(resp.success){
+ if (resp.result && resp.result.sections !== undefined){
+ labelSections(resp.result.sections);
+ setSections(Utils.sortByEmbeddedKey(resp.result.sections));
+ setPagginationHidden(false);
+ setPrevDisabled(index <= 0);
+ }
+ }
+ setLoading(false);
+ })();
+ }else{
+ const packageType = Utils.packageTypeFromKey(currentKey);
+ const type = Utils.typeFromKey(currentKey);
+ const name = Utils.nameFromKey(currentKey);
+ if (type !== undefined && name !== undefined){
+ (async () => {
+ const resp = await nfcRes.get(packageType, type, name, "", index, size);
+ if(resp.success){
+ if(resp.result && resp.result.sections !== undefined){
+ labelSections(resp.result.sections);
+ setSections(Utils.sortByEmbeddedKey(resp.result.sections));
+ setPagginationHidden(false);
+ // TODO: check if need to setCurrentKey here
+ setCurrentKey(Utils.formatKey(packageType, type, name));
+ setPrevDisabled(index <= 0);
+ }
+ }
+ setLoading(false);
+ })();
+ // alert( "showing NFC entries for: " + $scope.currentKey);
+ }
+ }
+ };
+ const changePageSize = currentSize => {
+ updatePage({"size": currentSize, "index": 0});
+ queryByPageIndexAndSize(page.current.index, page.current.size);
+ };
+ const changePageNumber = e => {
+ if(e.keyCode === 13) {
+ const pageIndex = parseInt(e.target.value, 10);
+ updatePage({"index": pageIndex});
+ queryByPageIndexAndSize(page.current.index, page.current.size);
+ }
+ };
+ const prevPage = () => {
+ const [curIndex, curSize] = [page.current.index-1, page.current.size];
+ queryByPageIndexAndSize(curIndex, curSize);
+ updatePage({"index": curIndex, "size": curSize});
+ };
+ const nextPage = () => {
+ const curIndex = page.current.index + 1;
+ queryByPageIndexAndSize(curIndex, page.current.size);
+ updatePage({"index": curIndex});
+ };
+
+ const handleSearch = e => {
+ e.preventDefault();
+ // TODO: not implemented yet!
+ };
+
+ return
+
+ {
+ loadingSection &&
+ }
+
+ Not-Found Cache Entries for:
+
+
+
+
+ {
+ nfcStoreKeys.map(key => {Utils.keyLabel(key)} )
+ }
+ {' '}
+
+
+ Show All
+ Clear All
+
+
+
+ Search:
+
+
+
+ Debug Data
+
+
+
+ {loading &&
}
+ {message && message.trim() !== "" &&
{message}
}
+ {error && error.trim() !== "" &&
{error}
}
+ {(message && message.trim() !== "" || error && error.trim() !== "") &&
}
+ {
+ sections && sections.length > 0 &&
+
+ {
+ sections.map(section =>
+
+ {
+ section.paths && section.paths.length > 0 &&
+ {
+ section.paths.map(path =>
+
+ )
+ }
+
+ }
+ )
+ }
+
+ }
+ {
+ !paginationHidden &&
+ Page Size:
+ {
+ changePageSize(e.target.value);
+ }}>
+ {
+ pageSizes.map(pageSize => {pageSize} )
+ }
+
+ {
+ !prevDisabled &&
+ }
+
+
+
+ }
+
+ ;
}
diff --git a/src/main/webui/src/app/components/content/addons/NFC.test.jsx b/src/main/webui/src/app/components/content/addons/NFC.test.jsx
new file mode 100644
index 0000000..1d59b9f
--- /dev/null
+++ b/src/main/webui/src/app/components/content/addons/NFC.test.jsx
@@ -0,0 +1,130 @@
+/**
+ * Copyright (C) 2023 Red Hat, Inc. (https://github.com/Commonjava/indy-ui-service)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import React from "react";
+import {render, screen, cleanup, waitFor, within} from '@testing-library/react';
+import userEvent from "@testing-library/user-event";
+import '@testing-library/jest-dom';
+import fetchMock from "fetch-mock";
+import NFC from "./NFC.jsx";
+
+beforeEach(()=>{
+ fetchMock.restore();
+});
+
+afterEach(() => {
+ cleanup();
+});
+
+const mockEndpoints = {items: [
+ {
+ "packageType": "maven",
+ "name": "central",
+ "type": "remote",
+ "key": "maven:remote:central",
+ "storeKey": "maven:remote:central",
+ "storeType": "remote",
+ "resource_uri": "http://localhost:4000/api/content/maven/remote/central"
+ },
+ {
+ "packageType": "maven",
+ "name": "public",
+ "type": "group",
+ "key": "maven:group:public",
+ "storeKey": "maven:group:public",
+ "storeType": "group",
+ "resource_uri": "http://localhost:4000/api/content/maven/group/public"
+ },
+ {
+ "packageType": "maven",
+ "name": "tYMtROxQUA",
+ "type": "hosted",
+ "key": "maven:hosted:tYMtROxQUA",
+ "storeKey": "maven:hosted:tYMtROxQUA",
+ "storeType": "hosted",
+ "resource_uri": "http://localhost:4000/api/content/maven/hosted/tYMtROxQUA"
+ }
+]};
+
+const mockAllNFCItems = {
+ sections: [
+ {
+ "key": "maven:remote:central",
+ "paths": [
+ "/8852/5330",
+ "/5687/5449",
+ "/6781/5509"
+ ]
+ },
+ {
+ "key": "maven:group:public",
+ "paths": [
+ "/5071/7765",
+ "/9606/6819",
+ "/9647/3899",
+ "/2185/2201"
+ ]
+ },
+ {
+ "key": "maven:hosted:tYMtROxQUA",
+ "paths": [
+ "/4960/9412",
+ "/1687/3470",
+ "/2960/4280",
+ "/1140/8242",
+ "/8854/5915",
+ "/9425/1833",
+ "/8009/6333",
+ "/7481/6826",
+ "/3495/8758"
+ ]
+ }
+ ]
+};
+
+describe('NFC tests', () => {
+ it("Verify NFC", async () => {
+ const user = userEvent.setup();
+ fetchMock.mock(`/api/admin/stores/query/endpoints/all`, {status: 200, body: JSON.stringify(mockEndpoints)});
+ fetchMock.mock("/api/nfc?pageIndex=0&pageSize=10", {status: 200, body: JSON.stringify(mockAllNFCItems)});
+ render(
);
+ const nfcSelect = screen.getByRole("nfcSel");
+ await waitFor(() => {
+ expect(nfcSelect).toHaveValue("");
+ });
+ const showAllButton = screen.getByRole("button", {name: "Show All"});
+
+ await waitFor(() => {
+ expect(screen.getByRole("option", {name: "central (remote; maven)"})).toBeInTheDocument();
+ expect(showAllButton).toBeInTheDocument();
+ });
+
+ await user.click(showAllButton);
+ await waitFor(() => {
+ let section = screen.getByRole("section-maven:remote:central");
+ expect(section).toBeInTheDocument();
+ expect(within(section).getByText("/8852/5330")).toBeInTheDocument();
+
+ section = screen.getByRole("section-maven:group:public");
+ expect(section).toBeInTheDocument();
+ expect(within(section).getByText("/5071/7765")).toBeInTheDocument();
+
+ section = screen.getByRole("section-maven:hosted:tYMtROxQUA");
+ expect(section).toBeInTheDocument();
+ expect(within(section).getByText("/9425/1833")).toBeInTheDocument();
+ });
+ });
+});
diff --git a/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx b/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx
index 21f023c..219bcda 100644
--- a/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx
+++ b/src/main/webui/src/app/components/content/common/PackageTypeSelect.jsx
@@ -51,7 +51,7 @@ export const PackageTypeSelect = ({register, formErrors}) =>{
state.pkgTypes.map(type =>
{type} )
}
{' '}
- {formErrors && formErrors.packageType?.type === "required" &&
Package Type is required }
+ {formErrors && formErrors.packageType?.type === "required" &&
Package Type is required }
;
};
diff --git a/src/main/webui/src/app/components/content/common/PackageTypeSelect.test.jsx b/src/main/webui/src/app/components/content/common/PackageTypeSelect.test.jsx
index 01cbd3a..a8a08f0 100644
--- a/src/main/webui/src/app/components/content/common/PackageTypeSelect.test.jsx
+++ b/src/main/webui/src/app/components/content/common/PackageTypeSelect.test.jsx
@@ -61,9 +61,7 @@ describe('PackageTypeSelect tests', () => {
it("Verify PackageTypeSelect for value change", async ()=>{
const {selectOptions} = userEvent.setup();
- let value = "";
render(
);
- expect(value).toBe("");
await waitFor(() => {
expect(screen.getByRole("pkgTypeSel")).toHaveValue("");
});
diff --git a/src/main/webui/src/app/components/content/hosted/HostedEdit.jsx b/src/main/webui/src/app/components/content/hosted/HostedEdit.jsx
index 427463a..8c31943 100644
--- a/src/main/webui/src/app/components/content/hosted/HostedEdit.jsx
+++ b/src/main/webui/src/app/components/content/hosted/HostedEdit.jsx
@@ -159,8 +159,8 @@ export default function HostedEdit() {
{' '}
- {errors.name?.type === "required" && Name is required }
- {errors.name?.type === "maxLength" && Name's length should be less than 50 }
+ {errors.name?.type === "required" && Name is required }
+ {errors.name?.type === "maxLength" && Name's length should be less than 50 }
:
{store.name}
}
@@ -190,7 +190,7 @@ export default function HostedEdit() {
Disable Timeout:
{' '}
- {errors.disable_timeout &&
Not a valid number }
+ {errors.disable_timeout &&
Not a valid number }
diff --git a/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx b/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx
index 631cc46..59cb92f 100644
--- a/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx
+++ b/src/main/webui/src/app/components/content/remote/RemoteEdit.jsx
@@ -132,8 +132,8 @@ export default function RemoteEdit() {
{' '}
- {errors.name?.type === "required" && Name is required }
- {errors.name?.type === "maxLength" && Name's length should be less than 50 }
+ {errors.name?.type === "required" && Name is required }
+ {errors.name?.type === "maxLength" && Name's length should be less than 50 }
:
{store.name}
}
@@ -158,7 +158,7 @@ export default function RemoteEdit() {
Disable Timeout:
{' '}
- {errors.disable_timeout && Not a valid number }
+ {errors.disable_timeout && Not a valid number }
@@ -167,8 +167,8 @@ export default function RemoteEdit() {
Remote URL:
{' '}
- {errors.url?.type==="required" && Remote URL is required }
- {errors.url?.type==="pattern" && Not a valid URL }
+ {errors.url?.type==="required" && Remote URL is required }
+ {errors.url?.type==="pattern" && Not a valid URL }
diff --git a/src/main/webui/src/app/components/styles/indy.css b/src/main/webui/src/app/components/styles/indy.css
index cd4b900..4283868 100644
--- a/src/main/webui/src/app/components/styles/indy.css
+++ b/src/main/webui/src/app/components/styles/indy.css
@@ -442,8 +442,8 @@ label, .label{
}
.pagination{
- float: right;
- margin-bottom: 6px;
+ float: right;
+ margin-bottom: 6px;
}
.loader {
@@ -455,6 +455,6 @@ label, .label{
box-sizing: border-box;
}
-.alert {
+.indy-alert {
color: red;
}
\ No newline at end of file
diff --git a/src/main/webui/src/app/utils/AppUtils.js b/src/main/webui/src/app/utils/AppUtils.js
index dab87dc..6d0468e 100644
--- a/src/main/webui/src/app/utils/AppUtils.js
+++ b/src/main/webui/src/app/utils/AppUtils.js
@@ -196,5 +196,43 @@ export const Utils = {
desc = 'No description provided.';
}
return desc;
- }
+ },
+ formatKey: (packageType, type, name)=>`${packageType}:${type}:${name}`,
+ keyLabel: key => {
+ const parts = key.split(':');
+ return parts[2] + " (" + parts[1] + "; " + parts[0] + ")";
+ },
+ // Sort by: type (group, remote, hosted), packageType, name
+ sortByEmbeddedKey: items => {
+ if (items === undefined){
+ return items;
+ }
+
+ const typeOrder = ['group', 'remote', 'hosted'];
+ return items.sort((a, b) =>{
+ const ap = a.key.split(':');
+ const bp = b.key.split(':');
+
+ const ati = typeOrder.indexOf(ap[1]);
+ const bti = typeOrder.indexOf(bp[1]);
+
+ if (ati !== bti){
+ return ati < bti ? -1 : 1;
+ }
+
+ if (ap[0] < bp[0]){
+ return -1;
+ }else if (bp[0] < ap[0]){
+ return 1;
+ }
+
+ if (ap[2] < bp[2]){
+ return -1;
+ }else if (bp[2] < ap[2]){
+ return 1;
+ }
+
+ return 0;
+ });
+ },
};
diff --git a/src/main/webui/src/app/utils/RestClient.js b/src/main/webui/src/app/utils/RestClient.js
index 16227d5..35353b4 100644
--- a/src/main/webui/src/app/utils/RestClient.js
+++ b/src/main/webui/src/app/utils/RestClient.js
@@ -45,6 +45,30 @@ const jsonRest ={
const BASE_STORE_API_PATH = "/api/admin/stores";
const storeAPIEndpoint = (pkgType, type, name) => `${BASE_STORE_API_PATH}/${pkgType}/${type}/${name}`;
+const BASE_NFC_API_PATH = "/api/nfc";
+const nfcAPIEndpoint = (pkgType, type, name, path) => {
+ let result = `${BASE_NFC_API_PATH}/${pkgType}/${type}/${name}`;
+ if(path.trim() !== ""){
+ const encodedPath = encodeURIComponent(path);
+ result += `/${encodedPath}`;
+ }
+ return result;
+};
+
+const genPageParam = (index, size) => {
+ let queryParam = "";
+ if(index >= 0) {
+ queryParam = `pageIndex=${index}`;
+ }
+ if(size > 0){
+ if(queryParam.length > 0){
+ queryParam += `&`;
+ }
+ queryParam += `pageSize=${size}`;
+ }
+ return queryParam;
+};
+
const handleResponse = async response => {
if (response.ok){
let result = {};
@@ -147,7 +171,35 @@ const IndyRest = {
const response = await jsonRest.get('/api/admin/auth/userinfo');
return handleResponse(response);
}
- }
+ },
+ nfcRes: {
+ query: async (index, size) => {
+ const queryParam = genPageParam(index,size);
+ let apiPath = `${BASE_NFC_API_PATH}`;
+ if(queryParam.length > 0){
+ apiPath += `?${queryParam}`;
+ }
+ const response = await jsonRest.get(`${apiPath}`);
+ return handleResponse(response);
+ },
+ get: async (pkgType, type, name, path, index, size) => {
+ const queryParam = genPageParam(index,size);
+ let apiPath = nfcAPIEndpoint(pkgType, type, name, path);
+ if(queryParam.length > 0){
+ apiPath += `?${queryParam}`;
+ }
+ const response = await jsonRest.get(apiPath);
+ return handleResponse(response);
+ },
+ deleteAll: async () => {
+ const response = await http.delete(`${BASE_NFC_API_PATH}`);
+ return handleResponse(response);
+ },
+ delete: async (pkgType, type, name, path) => {
+ const response = await http.delete(nfcAPIEndpoint(pkgType, type, name, path));
+ return handleResponse(response);
+ }
+ },
};
export {IndyRest, BASE_STORE_API_PATH};
diff --git a/src/main/webui/src/server/app.js b/src/main/webui/src/server/app.js
index af8893b..881a180 100644
--- a/src/main/webui/src/server/app.js
+++ b/src/main/webui/src/server/app.js
@@ -20,6 +20,8 @@ const server = app.listen(Config.SERVER_PORT, () => {
});
app.use(express.static('dist'));
+const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
+
// For direct url bar addressing, will send home page directly for client router rendering
app.get([Config.APP_ROOT, `${Config.APP_ROOT}/*`, '/'], (req, res) => {
res.sendFile(indexHtml);
@@ -48,7 +50,8 @@ app.get('/api/stats/all-endpoints', (req, res) => {
// stats APIs end
// endpoints and storekeys
-app.get('/api/admin/stores/query/endpoints/:packageType', (req, res) => {
+app.get('/api/admin/stores/query/endpoints/:packageType', async (req, res) => {
+ await sleep(2000);
const [pkgType] = [req.params.packageType];
const statsEndpointsFile = path.resolve(__dirname, `./mock/list/FakeAllEndPoints.json`);
const list = require(statsEndpointsFile);
@@ -87,8 +90,6 @@ const decideMockListFile = (packgeType, type) => {
};
-const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
-
// For store listing
app.get(`${STORE_API_BASE}/:packageType/:type`, async (req, res) => {
await sleep(2000);
@@ -195,3 +196,58 @@ app.get('/api/admin/auth/userinfo', (req, res) => {
const testUser = {userName: "indy", roles: ["admin", "power-user", "user"]};
res.status(200).json(testUser);
});
+
+// Mock NFC APIs
+app.get(`/api/nfc/:packageType/:type/:name`, async (req, res) => {
+ await sleep(2000);
+ const [pkgType, type, name] = [req.params.packageType, req.params.type, req.params.name];
+ const storeKey = `${pkgType}:${type}:${name}`;
+ console.log(`Fetching nfc for ${storeKey}`);
+ const allNFCItems = require('./mock/list/FakeNFCItems.json');
+ const nfcItems = allNFCItems.sections.filter(s=>s.key===storeKey);
+ console.log(`Returning nfc items for ${storeKey}: ${nfcItems}`);
+ const result = {
+ sections: nfcItems
+ };
+ res.status(200).json(result);
+});
+
+app.get('/api/nfc', async (req, res) => {
+ await sleep(2000);
+ const [pageIndex, pageSize] = [req.query.pageIndex, req.query.pageSize];
+ const allNFCItems = require('./mock/list/FakeNFCItems.json');
+ allNFCItems.sections.sort();
+ if(pageIndex && pageSize){
+ let [start, size] = [parseInt(pageIndex, 10), parseInt(pageSize, 10)];
+ let end = start+size;
+ const sections = allNFCItems.sections;
+ if(end > sections.length){
+ end = sections.length;
+ }
+ const result = {
+ sections: allNFCItems.sections.slice(start, end)
+ };
+ res.status(200).json(result);
+ }else{
+ res.status(200).json(allNFCItems);
+ }
+});
+
+app.delete('/api/nfc', (req, res)=>{
+ console.log("Deleting all nfc setcions");
+ res.status(204).json({"msg": "All sections deleted"});
+});
+
+app.delete(`/api/nfc/:packageType/:type/:name`, (req, res) => {
+ const [pkgType, type, name] = [req.params.packageType, req.params.type, req.params.name];
+ const storeKey = `${pkgType}:${type}:${name}`;
+ console.log(`Deleting nfc for section ${storeKey}`);
+ res.status(204).json({"msg": "section deleted"});
+});
+
+app.delete(`/api/nfc/:packageType/:type/:name/:path`, (req, res) => {
+ const [pkgType, type, name, nfcPath] = [req.params.packageType, req.params.type, req.params.name, req.params.path];
+ const storeKey = `${pkgType}:${type}:${name}`;
+ console.log(`Deleting nfc path ${nfcPath} for ${storeKey}`);
+ res.status(204).json({"msg": "Path in section deleted"});
+});
diff --git a/src/main/webui/src/server/mock/list/FakeNFCItems.json b/src/main/webui/src/server/mock/list/FakeNFCItems.json
new file mode 100644
index 0000000..712432e
--- /dev/null
+++ b/src/main/webui/src/server/mock/list/FakeNFCItems.json
@@ -0,0 +1,1913 @@
+{
+ "sections":[
+ {
+ "key": "maven:group:build_org-keycloak-keycloak-parent-4-x_20180515.1724",
+ "paths": [
+ "/7045/2311",
+ "/6607/7336",
+ "/6308/791",
+ "/833/7285",
+ "/211/4668",
+ "/4337/2074",
+ "/2967/6828",
+ "/1905/2667"
+ ]
+ },
+ {
+ "key": "maven:group:build_org-keycloak-keycloak-parent-4-x_20180531.0218",
+ "paths": [
+ "/4184/937",
+ "/4403/2420"
+ ]
+ },
+ {
+ "key": "maven:group:build_org-keycloak-keycloak-nodejs-auth-utils-3-xnpm_1-2-stage-4_20180104.1216",
+ "paths": [
+ "/884/2478",
+ "/3933/1959",
+ "/3851/8130",
+ "/7357/5585",
+ "/159/1806",
+ "/6702/5613"
+ ]
+ },
+ {
+ "key": "maven:group:build_vertx-infinispan-3-5-1_20180705.1313",
+ "paths": [
+ "/3747/1062",
+ "/5989/1327",
+ "/8487/7893",
+ "/6434/3515"
+ ]
+ },
+ {
+ "key": "maven:group:public",
+ "paths": [
+ "/5071/7765",
+ "/9606/6819",
+ "/9647/3899",
+ "/2185/2201"
+ ]
+ },
+ {
+ "key": "maven:hosted:FisZYfNgpR",
+ "paths": [
+ "/7541/6638",
+ "/1843/2390",
+ "/5382/8116",
+ "/8569/7908",
+ "/6127/9393",
+ "/333/8221",
+ "/5357/204",
+ "/3282/9908",
+ "/4257/9673"
+ ]
+ },
+ {
+ "key": "maven:hosted:tYMtROxQUA",
+ "paths": [
+ "/4960/9412",
+ "/1687/3470",
+ "/2960/4280",
+ "/1140/8242",
+ "/8854/5915",
+ "/9425/1833",
+ "/8009/6333",
+ "/7481/6826",
+ "/3495/8758"
+ ]
+ },
+ {
+ "key": "maven:hosted:LYnrVCMAZP",
+ "paths": [
+ "/8580/9454",
+ "/5024/7120",
+ "/9500/9566"
+ ]
+ },
+ {
+ "key": "maven:hosted:build_kie-soup_20180628.0657",
+ "paths": [
+ "/5077/9078",
+ "/8247/290",
+ "/8927/8530",
+ "/9149/5895",
+ "/1164/2209",
+ "/6663/4733",
+ "/3880/214"
+ ]
+ },
+ {
+ "key": "maven:remote:central",
+ "paths": [
+ "/8852/5330",
+ "/5687/5449",
+ "/6781/5509"
+ ]
+ },
+ {
+ "key": "maven:remote:i-maven-restlet-4",
+ "paths": [
+ "/4080/972",
+ "/4409/1410",
+ "/9726/643",
+ "/3016/8850",
+ "/4420/2007",
+ "/3667/1977",
+ "/618/5355"
+ ]
+ },
+ {
+ "key": "maven:remote:mrrc-ga",
+ "paths": [
+ "/9698/9050",
+ "/888/1548",
+ "/8964/2527",
+ "/9809/3278",
+ "/7962/8260"
+ ]
+ },
+ {
+ "key": "maven:remote:repo.eclipse.org",
+ "paths": []
+ },
+ {
+ "key": "maven:remote:microprofile.repo.eclipse.org",
+ "paths": []
+ },
+ {
+ "key": "maven:remote:japidiff",
+ "paths": [
+ "/1640/7396",
+ "/3562/9538",
+ "/1953/9558",
+ "/9536/1142",
+ "/964/7177",
+ "/4592/6827"
+ ]
+ },
+ {
+ "key": "maven:remote:spring-plugins-snapshot",
+ "paths": []
+ },
+ {
+ "key": "maven:remote:sonatype-snapshots",
+ "paths": [
+ "/5487/6422",
+ "/1835/1461",
+ "/1545/4789",
+ "/8588/9113",
+ "/9905/1789",
+ "/61/4934",
+ "/6239/8484"
+ ]
+ },
+ {
+ "key": "maven:remote:snapshots",
+ "paths": [
+ "/5437/6917",
+ "/4124/1403",
+ "/674/7716",
+ "/3373/3110",
+ "/6068/2136",
+ "/3380/4919",
+ "/212/7310",
+ "/2086/4811",
+ "/7137/86"
+ ]
+ },
+ {
+ "key": "maven:remote:apache.snapshots",
+ "paths": [
+ "/1494/2689",
+ "/1012/7775"
+ ]
+ },
+ {
+ "key": "maven:remote:repository.jboss.com",
+ "paths": [
+ "/9809/1735",
+ "/6647/6556",
+ "/2796/4724",
+ "/1900/3102",
+ "/5350/8259"
+ ]
+ },
+ {
+ "key": "maven:remote:eclipse.m2",
+ "paths": [
+ "/4069/819",
+ "/2897/832",
+ "/4688/207",
+ "/3175/7070",
+ "/5887/9431",
+ "/4599/1725"
+ ]
+ },
+ {
+ "key": "maven:remote:snmp4j.repo",
+ "paths": [
+ "/877/1285",
+ "/7511/193"
+ ]
+ },
+ {
+ "key": "npm:group:DA-temporary-builds",
+ "paths": [
+ "/2532/5485"
+ ]
+ },
+ {
+ "key": "npm:group:build-172077677927211008",
+ "paths": [
+ "/3795/6847",
+ "/5177/3262",
+ "/8151/6912",
+ "/7851/7836",
+ "/473/700"
+ ]
+ },
+ {
+ "key": "npm:group:DA",
+ "paths": [
+ "/7120/66",
+ "/5917/525"
+ ]
+ },
+ {
+ "key": "npm:group:builds-untested+shared-imports",
+ "paths": [
+ "/94/6225",
+ "/9872/6069",
+ "/3669/6534"
+ ]
+ },
+ {
+ "key": "npm:group:builds-untested+shared-imports+public",
+ "paths": [
+ "/5419/3179"
+ ]
+ },
+ {
+ "key": "npm:group:DApublic",
+ "paths": [
+ "/5934/1785",
+ "/7180/97",
+ "/5531/1512",
+ "/9666/6277",
+ "/283/8396",
+ "/2382/1541"
+ ]
+ },
+ {
+ "key": "npm:group:build-A4RWJFXAWIAAA",
+ "paths": [
+ "/6857/2411",
+ "/6053/2969"
+ ]
+ },
+ {
+ "key": "npm:group:public",
+ "paths": []
+ },
+ {
+ "key": "npm:group:shared-imports+public",
+ "paths": [
+ "/4727/4729",
+ "/1768/3557"
+ ]
+ },
+ {
+ "key": "npm:group:build-A4SLH57TGIAAA",
+ "paths": [
+ "/5602/4442",
+ "/6855/3009",
+ "/3756/231",
+ "/6151/5530"
+ ]
+ },
+ {
+ "key": "npm:group:temporary-builds",
+ "paths": [
+ "/730/813",
+ "/7673/9931",
+ "/3031/9943",
+ "/787/621",
+ "/8709/8731",
+ "/9130/3457"
+ ]
+ },
+ {
+ "key": "npm:group:build-175689795468152832",
+ "paths": [
+ "/4489/46",
+ "/8604/9060",
+ "/7741/877",
+ "/610/3812",
+ "/9103/3664",
+ "/9313/9351"
+ ]
+ },
+ {
+ "key": "npm:group:build-175645950118350848",
+ "paths": [
+ "/7320/7340",
+ "/7020/2412"
+ ]
+ },
+ {
+ "key": "npm:group:build-A4SLDYLJGIAAA",
+ "paths": [
+ "/3643/8688",
+ "/5951/7721",
+ "/469/4289"
+ ]
+ },
+ {
+ "key": "npm:group:shared-imports+yarn-public",
+ "paths": [
+ "/8981/625",
+ "/8026/1119",
+ "/9135/2008"
+ ]
+ },
+ {
+ "key": "npm:group:build-172056280052015104",
+ "paths": [
+ "/3533/1554",
+ "/9637/9139",
+ "/2634/8178",
+ "/9194/5170",
+ "/6130/2956",
+ "/937/5879",
+ "/5925/8665"
+ ]
+ },
+ {
+ "key": "npm:group:builds-untested",
+ "paths": [
+ "/2152/8121",
+ "/3686/3320",
+ "/4418/8988",
+ "/5210/1200",
+ "/2973/3302",
+ "/2046/9995"
+ ]
+ },
+ {
+ "key": "npm:group:yarn-public",
+ "paths": [
+ "/6883/9086",
+ "/2452/8206",
+ "/6592/6326",
+ "/1749/8920",
+ "/7765/634",
+ "/5626/8808"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1039",
+ "paths": [
+ "/7366/9797",
+ "/1715/8308",
+ "/9955/8753",
+ "/1173/6058",
+ "/7706/9953",
+ "/47/9725",
+ "/1670/8546",
+ "/2398/5207"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1545",
+ "paths": [
+ "/8571/7507",
+ "/3284/6197"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ARH4LMNVUVQAA",
+ "paths": [
+ "/8040/9846",
+ "/9935/4552",
+ "/3317/4077",
+ "/1180/3821",
+ "/9844/2167"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATMXTBCK2JIAA",
+ "paths": [
+ "/5692/2953",
+ "/6638/6050",
+ "/9228/7401",
+ "/4208/8100",
+ "/1033/9842",
+ "/2555/8480",
+ "/1665/5568",
+ "/7998/1822",
+ "/4652/9760"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLVX3EKJIAA",
+ "paths": [
+ "/7281/5044",
+ "/9147/5255",
+ "/8425/2648",
+ "/9262/1995",
+ "/9849/806",
+ "/4151/6608",
+ "/2253/4514",
+ "/4443/8784",
+ "/5788/9332"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1751",
+ "paths": [
+ "/5805/3267",
+ "/1386/4687",
+ "/7528/6687",
+ "/27/7292",
+ "/8250/1508",
+ "/2789/4885",
+ "/9947/7134",
+ "/3492/6033"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-172056280052015104",
+ "paths": [
+ "/8691/9175",
+ "/8094/1194"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATIPTNJS4TIAA",
+ "paths": [
+ "/40/5502",
+ "/4830/9390",
+ "/9239/2535",
+ "/3443/3372",
+ "/6421/8472"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-A4RWJFXAWIAAA",
+ "paths": [
+ "/4466/3948",
+ "/7240/9489",
+ "/2628/3016",
+ "/7515/9261",
+ "/2000/1139",
+ "/8605/1663",
+ "/7237/9386",
+ "/9390/6686",
+ "/4862/7377"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1318",
+ "paths": [
+ "/2462/7485",
+ "/674/7204",
+ "/815/1361"
+ ]
+ },
+ {
+ "key": "npm:hosted:shared-imports",
+ "paths": [
+ "/7435/807",
+ "/2634/7315",
+ "/4710/8132",
+ "/9410/3637",
+ "/9291/5149",
+ "/1347/3965",
+ "/9051/4278"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJMS5VM2JIAA",
+ "paths": [
+ "/6478/3575",
+ "/5403/5068"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJVTFPY2JIAA",
+ "paths": [
+ "/1267/8161",
+ "/8585/258",
+ "/6081/8349",
+ "/2044/7296",
+ "/8451/2814",
+ "/2007/6289"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1892",
+ "paths": [
+ "/6014/5116",
+ "/7055/7188",
+ "/3556/3185",
+ "/9565/7162",
+ "/5426/4271",
+ "/5137/4781",
+ "/3953/9676"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSJXFPXWUIAA",
+ "paths": [
+ "/3248/676",
+ "/7731/9787",
+ "/9108/8995",
+ "/6919/6707",
+ "/9624/2504",
+ "/8122/4777",
+ "/3073/5071",
+ "/9900/2138",
+ "/9184/4346"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATM6LQ22CJIAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ATJEAVIZYHIAA",
+ "paths": [
+ "/7218/5841",
+ "/9869/873"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANW6HFU3Y3AAA",
+ "paths": [
+ "/1869/6734",
+ "/4186/7624",
+ "/9289/3926",
+ "/5908/418",
+ "/19/8903",
+ "/7733/7094",
+ "/3328/2604",
+ "/6217/3960",
+ "/6692/4920"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-A4SK7ID3WIAAA",
+ "paths": [
+ "/5025/409",
+ "/240/7555",
+ "/7429/4259",
+ "/8115/1398",
+ "/9828/8498",
+ "/5514/8589"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ASJNWOAV2MQAA",
+ "paths": [
+ "/5455/1996",
+ "/2148/4045",
+ "/1703/2169",
+ "/2290/3783"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-177728051542118400",
+ "paths": [
+ "/8741/101",
+ "/9597/6115",
+ "/75/1146",
+ "/7240/7552",
+ "/3679/7627",
+ "/2114/4608"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ASE5VFCHXYIAA",
+ "paths": [
+ "/7333/7332",
+ "/7627/1315",
+ "/2412/3561",
+ "/61/8843",
+ "/853/6435",
+ "/8356/8774",
+ "/155/9193"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1915",
+ "paths": [
+ "/1352/8449",
+ "/1926/4166",
+ "/8595/829",
+ "/2063/3919",
+ "/5862/4623",
+ "/3419/4920",
+ "/2316/7720",
+ "/188/6402",
+ "/4162/6088"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-AUS2H4JNNWIAA",
+ "paths": [
+ "/3434/5497",
+ "/1043/1269",
+ "/7394/5209",
+ "/2711/8158",
+ "/9335/8377",
+ "/8397/1743"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1726",
+ "paths": [
+ "/1640/2534",
+ "/6483/3469",
+ "/6031/7906",
+ "/6625/7475",
+ "/4565/3227",
+ "/742/3015",
+ "/9839/9032",
+ "/2860/5064"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1393",
+ "paths": [
+ "/514/8902",
+ "/1537/8107",
+ "/777/6694",
+ "/289/1073",
+ "/3083/2577",
+ "/7105/7506"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1918",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ANSHZIJ2WUIAA",
+ "paths": [
+ "/6711/260",
+ "/8061/7994"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSC3XNBIJYAA",
+ "paths": [
+ "/2103/5271",
+ "/5093/6122",
+ "/3642/5495",
+ "/9321/7848",
+ "/982/3839",
+ "/2394/7618"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLTMUYKJIAA",
+ "paths": [
+ "/9106/5185",
+ "/1264/9234",
+ "/8081/6919"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJVZRQA2JIAA",
+ "paths": [
+ "/5664/7303",
+ "/9531/3855",
+ "/6889/418",
+ "/4832/3089"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSDID7VAJYAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-1753",
+ "paths": [
+ "/7828/113",
+ "/5130/4531",
+ "/1053/4432"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANWPAJ33IEQAA",
+ "paths": [
+ "/4113/3700",
+ "/8757/828",
+ "/4349/8003",
+ "/7147/4678",
+ "/787/924",
+ "/3836/5182"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATSAZTZKHQAAA",
+ "paths": [
+ "/597/8052",
+ "/4762/56",
+ "/1018/9904",
+ "/3429/9827",
+ "/8792/6756",
+ "/1678/5020",
+ "/2563/4432",
+ "/4143/6586"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1325",
+ "paths": [
+ "/3034/5040",
+ "/9662/6070"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1403",
+ "paths": [
+ "/7518/9829",
+ "/9919/738",
+ "/2861/7632"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1908",
+ "paths": [
+ "/1339/6792",
+ "/3390/6982",
+ "/5157/3055",
+ "/7272/35",
+ "/5981/2542",
+ "/2794/398",
+ "/9055/3232",
+ "/2392/913",
+ "/4190/249"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATMXX5UNCJIAA",
+ "paths": [
+ "/1616/6354",
+ "/9626/9828",
+ "/9118/322"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJVZHAOSJIAA",
+ "paths": [
+ "/7958/9283",
+ "/2614/5936",
+ "/1213/6894",
+ "/3481/3259",
+ "/7087/8271",
+ "/610/1333"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLN4KE2JIAA",
+ "paths": [
+ "/9664/8071",
+ "/829/1391",
+ "/2572/4928",
+ "/2320/5577",
+ "/9265/360",
+ "/1715/1408"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJBPKAUIHIAA",
+ "paths": [
+ "/2388/6544"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-AUSSLL6X5WIAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ATJV3HRICJIAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-1725",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-162851312008671232",
+ "paths": [
+ "/841/8684",
+ "/845/9655",
+ "/4369/5577",
+ "/9071/7000",
+ "/5127/7946",
+ "/6979/1622",
+ "/5239/1888",
+ "/7134/4518",
+ "/8285/8989"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATIMRBRAMTIAA",
+ "paths": [
+ "/2038/1853",
+ "/2491/7428",
+ "/2116/4192"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1255",
+ "paths": [
+ "/4744/3421",
+ "/2614/1160",
+ "/3061/9047"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1471",
+ "paths": [
+ "/6542/4313",
+ "/5011/2866",
+ "/334/356",
+ "/8906/530",
+ "/896/8002",
+ "/2915/4057",
+ "/9232/7390"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1537",
+ "paths": [
+ "/6969/2663",
+ "/4715/5023",
+ "/9177/8061",
+ "/9569/5914"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRDMIQY7QAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ANSJXYBWOUIAA",
+ "paths": [
+ "/9236/6613",
+ "/5886/5751",
+ "/7376/9518",
+ "/2869/6558",
+ "/6518/2745"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-850",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ANSJYI4V6UIAA",
+ "paths": [
+ "/2088/5222",
+ "/9137/5512",
+ "/4801/5744",
+ "/3277/2873",
+ "/2446/4701",
+ "/4156/6649",
+ "/7405/1121"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJVU4NKCJIAA",
+ "paths": [
+ "/3614/2561",
+ "/6462/2127",
+ "/5561/4832",
+ "/6803/8661",
+ "/8667/7716",
+ "/7680/2946",
+ "/7329/534",
+ "/2103/9142"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1081",
+ "paths": [
+ "/1432/7678"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATSAH55UPQAAA",
+ "paths": [
+ "/261/5896",
+ "/9235/981",
+ "/5728/2967",
+ "/5929/1503",
+ "/4715/8313"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1961",
+ "paths": [
+ "/233/5567",
+ "/1150/2992"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1302",
+ "paths": [
+ "/6428/8891",
+ "/2252/6592",
+ "/4104/9200",
+ "/3231/3756",
+ "/4590/1587",
+ "/566/1303",
+ "/2374/2811",
+ "/5495/8175"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1714",
+ "paths": [
+ "/4786/8198",
+ "/1848/3316",
+ "/3136/1268",
+ "/7155/6406",
+ "/1373/7627"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1780",
+ "paths": [
+ "/7682/3146",
+ "/867/6529",
+ "/6690/6736",
+ "/6711/9153",
+ "/7779/6830"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1397",
+ "paths": [
+ "/165/135",
+ "/2080/5820",
+ "/4992/7631",
+ "/8943/9160",
+ "/442/9855",
+ "/7896/7750",
+ "/133/8997",
+ "/5119/1354",
+ "/6513/7799"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1007",
+ "paths": [
+ "/8104/6197",
+ "/7066/3629"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1128",
+ "paths": [
+ "/5006/8730",
+ "/1568/6018",
+ "/9665/1176"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-174864544753614848",
+ "paths": [
+ "/5477/4631",
+ "/884/3081",
+ "/852/7358",
+ "/817/6218",
+ "/7573/971",
+ "/2300/5125",
+ "/8009/1477",
+ "/3617/3146"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1309",
+ "paths": [
+ "/7050/8234",
+ "/3339/209",
+ "/5276/1922",
+ "/4288/1376",
+ "/2470/14"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATI7SHYMQHIAA",
+ "paths": [
+ "/1778/9925",
+ "/7491/9308",
+ "/5483/1679",
+ "/4923/7673"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRRNKMA7QAA",
+ "paths": [
+ "/1433/2130",
+ "/4476/615",
+ "/5976/9864",
+ "/2928/5219",
+ "/4147/8670",
+ "/2822/5688"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1788",
+ "paths": [
+ "/4644/9686",
+ "/2052/3553",
+ "/4791/5024",
+ "/3333/6380",
+ "/5356/916",
+ "/1605/6810",
+ "/7903/9070",
+ "/2958/1861"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLUBI5KJIAA",
+ "paths": [
+ "/9164/5841",
+ "/5008/6385",
+ "/3493/9524",
+ "/4989/6031",
+ "/7989/2740"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATMUGZX4KJIAA",
+ "paths": [
+ "/2721/5045",
+ "/9281/1871",
+ "/1855/3741",
+ "/8809/710",
+ "/6597/546"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-A4RWOQJKGIAAA",
+ "paths": [
+ "/708/4711",
+ "/8261/2332",
+ "/2709/8995",
+ "/2341/5661",
+ "/4302/5123"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLPKQC2JIAA",
+ "paths": [
+ "/1194/6360",
+ "/8033/3958"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1791",
+ "paths": [
+ "/9235/1238",
+ "/8854/8574"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1300",
+ "paths": [
+ "/460/5198",
+ "/8168/7737"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANWONZKHYEQAA",
+ "paths": [
+ "/5376/1247"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATSCG6OIXQAAA",
+ "paths": [
+ "/541/7610",
+ "/7146/2160",
+ "/1523/6617",
+ "/919/6392",
+ "/4360/2592",
+ "/8258/4222",
+ "/4503/5309",
+ "/6871/3841",
+ "/3130/178"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-815",
+ "paths": [
+ "/6083/442",
+ "/2779/8732",
+ "/6823/9298",
+ "/4212/3962",
+ "/7144/7742",
+ "/7425/1409",
+ "/4343/3142",
+ "/8197/6634"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATI7SK7FAHIAA",
+ "paths": [
+ "/9450/2713",
+ "/412/3033",
+ "/5952/8680",
+ "/6153/665"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-898",
+ "paths": [
+ "/8419/1243",
+ "/6197/6912",
+ "/4656/2703",
+ "/4139/7466",
+ "/3575/490",
+ "/5255/5490"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSDHMTDYJYAA",
+ "paths": [
+ "/9629/8148"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1321",
+ "paths": [
+ "/7418/7008",
+ "/7043/8010",
+ "/9882/4756",
+ "/2806/6502",
+ "/8677/1845",
+ "/3312/5444"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJVTBYBSJIAA",
+ "paths": [
+ "/7694/121",
+ "/8577/7733"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1080",
+ "paths": [
+ "/9000/5123",
+ "/3767/2870",
+ "/2222/445",
+ "/8007/7712"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-AVWZQUIFB7YAA",
+ "paths": [
+ "/7379/139"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATRRSYMTXQAAA",
+ "paths": [
+ "/2257/2126"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-A4SLDYLJGIAAA",
+ "paths": [
+ "/6343/4377",
+ "/7783/2333",
+ "/2225/3707",
+ "/7110/5449",
+ "/5176/6552",
+ "/9861/7463"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRJQYOA7QAA",
+ "paths": [
+ "/8971/1822",
+ "/8429/2114",
+ "/1189/8664",
+ "/4017/8133",
+ "/8687/7722",
+ "/4837/3345",
+ "/3239/9202",
+ "/2488/8783",
+ "/6154/8087"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRIIWSY7QAA",
+ "paths": [
+ "/9051/6268",
+ "/4788/4718",
+ "/4443/7570",
+ "/9153/3226",
+ "/1535/1389",
+ "/4697/8901",
+ "/4230/1284",
+ "/8178/2066"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1588",
+ "paths": [
+ "/8871/2307"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1888",
+ "paths": [
+ "/180/7556",
+ "/7689/930",
+ "/1454/7984",
+ "/8951/9553",
+ "/6652/1770",
+ "/1489/1149",
+ "/4676/2319",
+ "/5087/9780"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1768",
+ "paths": [
+ "/7000/2411",
+ "/8833/1134",
+ "/8019/4018"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATERVB5IMBIAA",
+ "paths": [
+ "/7323/5206",
+ "/1766/2295",
+ "/4708/3391",
+ "/423/1953",
+ "/4449/6134",
+ "/8523/9346",
+ "/1720/4282",
+ "/3477/9340"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1777",
+ "paths": [
+ "/9318/8809",
+ "/6015/863",
+ "/7576/5250"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-177141949236137984",
+ "paths": [
+ "/8105/754",
+ "/6977/2537",
+ "/6124/7015",
+ "/7383/8261"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1201",
+ "paths": [
+ "/5509/5416",
+ "/844/3277",
+ "/4798/8043",
+ "/4658/4538",
+ "/3586/9544",
+ "/9113/8226"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLNQ54CJIAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-1349",
+ "paths": [
+ "/1394/7820",
+ "/9718/7582",
+ "/1124/729",
+ "/9791/8173",
+ "/6249/5793",
+ "/4807/2059"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-899",
+ "paths": [
+ "/3733/5282",
+ "/2386/7016"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNQ7FCSA7QAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ALNRN7GQA7QAA",
+ "paths": [
+ "/386/7375",
+ "/9560/8810",
+ "/8379/834",
+ "/3713/2839"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1940",
+ "paths": [
+ "/8814/3418"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-AVWYYBKEB7YAA",
+ "paths": [
+ "/1259/9374",
+ "/1251/5030",
+ "/8942/5735"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1746",
+ "paths": [
+ "/1131/2067",
+ "/578/2344",
+ "/7288/1044",
+ "/4440/9009",
+ "/8599/651",
+ "/3040/299",
+ "/3323/3012",
+ "/9435/4948",
+ "/3481/5532"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNZBOJ6XEAAA",
+ "paths": [
+ "/8031/2684",
+ "/1653/5646",
+ "/8256/7887"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-175002848044564480",
+ "paths": [
+ "/3336/5031",
+ "/8820/3610",
+ "/108/5717",
+ "/2573/8745",
+ "/9221/4499",
+ "/7103/5797",
+ "/4587/291",
+ "/5493/6446"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1723",
+ "paths": [
+ "/4428/4602",
+ "/8957/7512",
+ "/3948/2302",
+ "/5624/7382",
+ "/2102/1687",
+ "/8098/7513",
+ "/8687/3014"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJ2HX732JIAA",
+ "paths": [
+ "/4959/5619",
+ "/8727/2177",
+ "/3327/8346",
+ "/9916/8243",
+ "/3259/6035"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATKLQVNBSJIAA",
+ "paths": [
+ "/6949/437",
+ "/5657/8572",
+ "/4570/1364",
+ "/6790/3600",
+ "/4187/7119",
+ "/1793/2573"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRYNBKI7QAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-826",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-172293563091640320",
+ "paths": [
+ "/5135/715",
+ "/1354/5791",
+ "/8703/6245",
+ "/5219/3046",
+ "/5000/4925",
+ "/2577/1222",
+ "/553/502",
+ "/8307/8602",
+ "/4949/2271"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1755",
+ "paths": [
+ "/8161/2153",
+ "/2752/1107",
+ "/243/9629",
+ "/5776/5724",
+ "/9577/4215",
+ "/9614/3838",
+ "/6318/3457"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-AY7DGR2EPHAAA",
+ "paths": [
+ "/1631/9529",
+ "/6907/6726",
+ "/5442/307",
+ "/1189/7605",
+ "/6119/139",
+ "/6542/3683",
+ "/2157/490",
+ "/4482/6063",
+ "/6704/8441"
+ ]
+ },
+ {
+ "key": "npm:hosted:pnc-builds",
+ "paths": [
+ "/987/1200",
+ "/1362/1393",
+ "/2937/7776",
+ "/2849/7073",
+ "/4231/2999",
+ "/7519/9820",
+ "/181/5888"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1160",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-1715",
+ "paths": [
+ "/6710/2175",
+ "/7669/1683",
+ "/7603/7003",
+ "/7314/278",
+ "/1846/5332",
+ "/3509/3716",
+ "/59/5331",
+ "/7679/5702",
+ "/5645/3760"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-A4SLH57TGIAAA",
+ "paths": [
+ "/2141/475",
+ "/4188/2365",
+ "/4443/4797",
+ "/467/8808",
+ "/7859/5778",
+ "/85/7377",
+ "/9595/3845",
+ "/5352/6526",
+ "/282/5169"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALN37FAJ6DQAA",
+ "paths": [
+ "/4031/9874",
+ "/3292/5903",
+ "/6923/5299",
+ "/788/2285",
+ "/512/3937",
+ "/5764/7828",
+ "/2302/1904"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1200",
+ "paths": [
+ "/9215/9467",
+ "/7586/3755"
+ ]
+ },
+ {
+ "key": "npm:hosted:temporary-builds",
+ "paths": [
+ "/3337/9501",
+ "/4283/3505",
+ "/6990/8820",
+ "/4867/1243",
+ "/3747/8580",
+ "/9968/570",
+ "/4562/9201"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1287",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-1189",
+ "paths": [
+ "/5563/896",
+ "/6938/4271",
+ "/4516/239"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNZDFZSHEAAA",
+ "paths": [
+ "/2145/5314",
+ "/1882/5515"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-infinispan-js-client",
+ "paths": [
+ "/404/3846",
+ "/6371/2803",
+ "/4911/4005",
+ "/8842/899",
+ "/4563/3058",
+ "/5267/9139",
+ "/1370/1824",
+ "/5227/601"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1742",
+ "paths": [
+ "/3754/436",
+ "/5887/1101",
+ "/7276/9905",
+ "/767/5849",
+ "/1320/5391",
+ "/672/202",
+ "/1183/280",
+ "/2728/6354",
+ "/4930/4522"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1030",
+ "paths": [
+ "/4447/2387",
+ "/8133/5548",
+ "/5584/7238",
+ "/3940/2116",
+ "/8951/4697",
+ "/7927/4694",
+ "/2620/8727",
+ "/1991/9833"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSIHDLHGUIAA",
+ "paths": [
+ "/1399/5130",
+ "/8425/2612",
+ "/5601/1772",
+ "/9603/3327",
+ "/1448/9029",
+ "/8131/6892"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1770",
+ "paths": [
+ "/1161/7992",
+ "/2000/7532"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSJWTPYOUIAA",
+ "paths": [
+ "/7112/8901",
+ "/7914/1009",
+ "/1330/3103"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1400",
+ "paths": [
+ "/5403/8728",
+ "/6309/9798",
+ "/163/7812",
+ "/7217/2127",
+ "/9193/7170"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1526",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-172077677927211008",
+ "paths": [
+ "/6777/8119",
+ "/1086/9145",
+ "/3259/9414"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-590",
+ "paths": [
+ "/6725/6972",
+ "/9156/352",
+ "/7704/8740",
+ "/8358/9718"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1728",
+ "paths": [
+ "/5722/3382",
+ "/4209/1883",
+ "/6498/1858",
+ "/308/8113",
+ "/1673/6525"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRSR4LQ7QAA",
+ "paths": [
+ "/9399/8104",
+ "/8740/7770",
+ "/4237/9057",
+ "/824/4308",
+ "/7155/2363",
+ "/2431/5435",
+ "/1393/2500",
+ "/6557/7342"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSDJOOKAJYAA",
+ "paths": [
+ "/4659/5707",
+ "/2591/3284",
+ "/5675/9053"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1745",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-ALNRWOK2I7QAA",
+ "paths": [
+ "/5039/2856",
+ "/5054/4541",
+ "/3187/6294"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1832",
+ "paths": [
+ "/4827/6256",
+ "/1462/1782",
+ "/7989/8405",
+ "/3197/284"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1774",
+ "paths": [
+ "/5767/6271",
+ "/7732/8299"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1036",
+ "paths": [
+ "/9393/1455",
+ "/575/2127",
+ "/1462/78",
+ "/1812/2321",
+ "/8693/6705",
+ "/9126/7374"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1402",
+ "paths": [
+ "/4737/3715"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1957",
+ "paths": [
+ "/596/1296"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1747",
+ "paths": [
+ "/6536/981"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATI7OKHBYHIAA",
+ "paths": [
+ "/4116/5386",
+ "/1567/5963",
+ "/1467/2234",
+ "/8051/4136",
+ "/1628/2702"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-831",
+ "paths": [
+ "/426/4891",
+ "/7870/2455",
+ "/1359/746",
+ "/4886/9848",
+ "/3801/81",
+ "/6379/8621"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1716",
+ "paths": [
+ "/17/6843",
+ "/4144/8436",
+ "/2967/9194",
+ "/4838/9003",
+ "/9635/7965"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1086",
+ "paths": [
+ "/458/1465",
+ "/5735/8555",
+ "/5946/4183",
+ "/3023/7786",
+ "/7060/4980",
+ "/3646/2320"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATM6P7AOSJIAA",
+ "paths": [
+ "/9282/2146"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-1916",
+ "paths": [
+ "/7574/2017",
+ "/3687/3047"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJMWZV2SJIAA",
+ "paths": [
+ "/9319/1184"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJL6BNJKJIAA",
+ "paths": [
+ "/4169/488",
+ "/5826/2700"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ALNRLW24Y7QAA",
+ "paths": [
+ "/6975/3557",
+ "/6721/7296",
+ "/8993/9666",
+ "/8392/2557",
+ "/7244/5638",
+ "/4323/3185",
+ "/9434/2979",
+ "/4/6259"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-175716749567217664",
+ "paths": [
+ "/9193/1622"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJCSYAPAHIAA",
+ "paths": [
+ "/4413/4821",
+ "/9041/1025",
+ "/8178/5054",
+ "/3139/4495",
+ "/9155/5885",
+ "/3752/7107"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ANSDI2U7QJYAA",
+ "paths": []
+ },
+ {
+ "key": "npm:hosted:build-1914",
+ "paths": [
+ "/9753/1944",
+ "/1189/7810",
+ "/5403/4896",
+ "/3546/8003",
+ "/7833/222",
+ "/4537/6764",
+ "/38/4498",
+ "/2512/3527"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATJVVTBOKJIAA",
+ "paths": [
+ "/8683/2712",
+ "/6243/5188"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-ATMVKBEFCJIAA",
+ "paths": [
+ "/7309/3782"
+ ]
+ },
+ {
+ "key": "npm:hosted:build-175699223500181504",
+ "paths": [
+ "/435/1920",
+ "/1308/8905",
+ "/3486/8840",
+ "/6146/4964",
+ "/6420/3358",
+ "/1904/7456"
+ ]
+ },
+ {
+ "key": "npm:remote:test-npmjs",
+ "paths": [
+ "/8719/4345",
+ "/2872/1051",
+ "/8189/622",
+ "/7741/3948",
+ "/8041/8588",
+ "/9998/2562",
+ "/6711/5579",
+ "/8819/1062",
+ "/5251/5020"
+ ]
+ },
+ {
+ "key": "npm:remote:yarnpkg",
+ "paths": [
+ "/432/9585",
+ "/5960/8549",
+ "/1757/9381",
+ "/2579/5945",
+ "/2676/4713",
+ "/6595/4424",
+ "/7932/1187",
+ "/869/9556"
+ ]
+ },
+ {
+ "key": "npm:remote:npmjs",
+ "paths": [
+ "/5199/4119",
+ "/7090/2598",
+ "/3606/3262",
+ "/8722/3798"
+ ]
+ }
+ ]
+}
\ No newline at end of file