UNPKG

@smapiot/piral-cloud-browser

Version:

Piral Cloud: Browser-usable API Client for the Piral Feed Service.

651 lines (647 loc) 22.4 kB
// ../feed-client/src/fetch.ts function fetchWithoutToken(client, url, init = {}) { const headers = new client.Headers(init.headers); if (init.body instanceof client.FormData) { } else if (!headers.has("content-type")) { headers.append("content-type", "application/json"); } return client.fetch(url, { ...client.defaults, ...init, headers }); } function fetchWithToken(client, url, init = {}) { return client.getAuthorizationHeader().then((header) => { if (header && typeof header === "string") { return fetchWithoutToken(client, url, { ...client.defaults, ...init, headers: { ...init.headers || {}, authorization: header } }); } return fetchWithoutToken(client, url, init); }); } // ../feed-client/src/http.ts function getJsonResponse(res) { const json = res.json(); if (!res.ok) { return json.then((err) => { throw new Error(err?.message ?? res.statusText); }); } return json; } function toQueryValue(value) { if (typeof value === "string") { return value; } else if (value instanceof Date) { return value.toISOString(); } else { return `${value}`; } } function makeQueryString(query) { return Object.keys(query).filter((n) => query[n] !== void 0).map((n) => `${n}=${toQueryValue(query[n])}`).join("&"); } function getDefaultHost() { if (typeof document !== "undefined") { return document.location.origin; } return ""; } function mac() { return new AbortController(); } function mri(ac) { return { signal: ac.signal }; } var FeedServiceApiClient = class { constructor(http, host = getDefaultHost()) { this.http = http; this.host = host; this._listeners = {}; } on(name, handler) { const handlers = this._listeners[name] || (this._listeners[name] = []); handlers.push(handler); } off(name, handler) { const handlers = this._listeners[name] || (this._listeners[name] = []); const index = handlers.indexOf(handler); index >= 0 && handlers.splice(index, 1); } once(name, handler) { const wrappedHandler = (ev) => { this.off(name, wrappedHandler); handler(ev); }; this.on(name, wrappedHandler); } emit(name, ev) { const handlers = this._listeners[name]; handlers?.forEach((handler) => handler(ev)); } getUrl(path) { const host = this.host; return `${host}/api/v1/${path}`; } getEvents() { const url = this.getUrl("events"); return url.replace("http", "ws"); } doAny(path, init) { const url = this.getUrl(path); return fetchWithToken(this.http, url, init).then((res) => { if (res.status === 401) { const delays = []; this.emit("unauthorized", { res, retry(delay) { delays.push(delay); } }); if (delays.length > 0) { return Promise.all(delays).then( () => { return fetchWithToken(this.http, url, init); }, () => { return res; } ); } } else if (res.status >= 500 && res.status < 600) { throw new Error(`HTTP call failed with status ${res.status}: ${res.statusText}`); } return res; }).then(getJsonResponse); } doGet(path, init = {}) { return this.doAny(path, { ...init, method: "GET" }); } doPost(path, content, init = {}) { const { FormData: FormData2 } = this.http; const body = content instanceof FormData2 ? content : JSON.stringify(content); return this.doAny(path, { ...init, method: "POST", body }); } doPut(path, content, init = {}) { const { FormData: FormData2 } = this.http; const body = content instanceof FormData2 ? content : JSON.stringify(content); return this.doAny(path, { ...init, method: "PUT", body }); } doDelete(path, init = {}) { return this.doAny(path, { ...init, method: "DELETE" }); } getPilets(ac = mac()) { return this.doQueryCurrentPilets("cloud", ac); } doQueryFeeds(ac = mac()) { return this.doGet(`feed`, mri(ac)); } doQueryFeed(feed, ac = mac()) { return this.doGet(`feed/${feed}`, mri(ac)); } doQueryValidEnvSourceTags(feed, eid, offset, count, ac = mac()) { const queryString = makeQueryString({ eid, offset, count }); return this.doGet(`feed/${feed}/tags?${queryString}`, mri(ac)); } doQueryEnvironments(feed, ac = mac()) { return this.doGet(`feed/${feed}/environments`, mri(ac)); } doQueryEnvironment(feed, eid, ac = mac()) { return this.doGet(`feed/${feed}/environments/${eid}`, mri(ac)); } doAddEnvironment(feed, content, ac = mac()) { return this.doPost(`feed/${feed}/environments`, content, mri(ac)); } doUpdateEnvironment(feed, eid, content, ac = mac()) { return this.doPut(`feed/${feed}/environments/${eid}`, content, mri(ac)); } doDeleteEnvironment(feed, eid, ac = mac()) { return this.doDelete(`feed/${feed}/environments/${eid}`, mri(ac)); } doQueryEnvironmentElevationReviews(feed, eid, ac = mac()) { return this.doGet(`feed/${feed}/environments/${eid}/elevations`, mri(ac)); } doQueryFeedElevationReviews(feed, ac = mac()) { return this.doGet(`feed/${feed}/elevations`, mri(ac)); } doQueryEnvironmentElevationReview(feed, eid, ac = mac()) { return this.doGet(`feed/${feed}/environments/${eid}/elevations/${eid}`, mri(ac)); } doAddElevationReview(feed, eid, content, ac = mac()) { return this.doPost(`feed/${feed}/environments/${eid}/elevations`, content, mri(ac)); } doUpdateElevationReview(feed, eid, id, content, ac = mac()) { return this.doPut(`feed/${feed}/environments/${eid}/elevations/${id}`, content, mri(ac)); } doQueryElevationReviewComments(feed, eid, ac = mac()) { return this.doGet(`feed/${feed}/elevations/${eid}/comments`, mri(ac)); } doAddElevationReviewComment(feed, eid, content, ac = mac()) { return this.doPost(`feed/${feed}/elevations/${eid}/comments`, content, mri(ac)); } doQueryPages(feed, tag = "latest", ac = mac()) { return this.doGet(`feed/${feed}/page?tag=${tag}`, mri(ac)); } doUpdatePageSettings(feed, content, ac = mac()) { return this.doPut(`feed/${feed}/page`, content, mri(ac)); } doUpdatePage(feed, version, content, tag = "latest", ac = mac()) { return this.doPut(`feed/${feed}/page/${version}?tag=${tag}`, content, mri(ac)); } doPublishPage(feed, content, ac = mac()) { const { FormData: FormData2 } = this.http; const form = new FormData2(); form.append("version", content.version); form.append("type", content.type); form.append("embed", content.embed); if (content.tag) { form.append("tag", content.tag); } if (content.options) { form.append("options", JSON.stringify(content.options)); } if (content.files) { for (const [path, file] of content.files) { form.append(path, file); } } return this.doPost(`feed/${feed}/page`, form, mri(ac)); } doQueryAllPilets(feed, tag = "latest", view = "all", ac = mac()) { const queryString = makeQueryString({ tag, view }); return this.doGet(`feed/${feed}/pilets?${queryString}`, mri(ac)); } doQueryUploadedPilets(feed, name, offset = "", count = "20", ac = mac()) { const queryString = makeQueryString({ offset, count }); return this.doGet(`feed/${feed}/pilets/${name}/versions?${queryString}`, mri(ac)); } doPublishPilet(feed, tag, file, ac = mac()) { const { FormData: FormData2 } = this.http; const form = new FormData2(); form.append("file", file); form.append("tag", tag); return this.doPost(`pilet/${feed}`, form, mri(ac)); } doQueryCurrentPilets(feed, ac = mac()) { return this.doGet(`pilet/${feed}`, mri(ac)).then((res) => res.items); } doQueryPiletDetails(feed, pilet, tag = "latest", ac = mac()) { return this.doGet(`feed/${feed}/pilets/${pilet}?tag=${tag}`, mri(ac)); } doQueryPiletReadme(feed, pilet, ac = mac()) { return this.doGet(`feed/${feed}/pilets/${pilet}/readme`, mri(ac)); } doQueryFeedExists(feed, ac = mac()) { return this.doGet(`feed/${feed}/check`, mri(ac)); } doQueryApiKeyScopes(ac = mac()) { return this.doGet(`api-key-scope`, mri(ac)); } doQueryApiKeys(feed, ac = mac()) { if (feed === "*") { return this.doQueryGeneralApiKeys(ac); } else { return this.doQueryFeedApiKeys(feed, ac); } } doQueryFeedApiKeys(feed, ac = mac()) { return this.doGet(`feed/${feed}/api-keys`, mri(ac)); } doQueryGeneralApiKeys(ac = mac()) { return this.doGet(`api-key`, mri(ac)); } doQueryFeatures(feed, ac = mac()) { return this.doGet(`feed/${feed}/features`, mri(ac)); } doQueryRules(feed, ac = mac()) { return this.doGet(`feed/${feed}/rules`, mri(ac)); } doCreateFeed(content, ac = mac()) { return this.doPost(`feed`, content, mri(ac)); } doAddFeature(feed, content, ac = mac()) { return this.doPost(`feed/${feed}/features`, content, mri(ac)); } doAddRule(feed, content, ac = mac()) { return this.doPost(`feed/${feed}/rules`, content, mri(ac)); } doGenerateApiKey(feed, content, ac = mac()) { if (feed === "*") { return this.doGenerateGeneralApiKey(content, ac); } else { return this.doGenerateFeedApiKey(feed, content, ac); } } doGenerateFeedApiKey(feed, content, ac = mac()) { return this.doPost(`feed/${feed}/api-keys`, content, mri(ac)); } doGenerateGeneralApiKey(content, ac = mac()) { return this.doPost(`api-key`, content, mri(ac)); } doDeleteFeed(feed, ac = mac()) { return this.doDelete(`feed/${feed}`, mri(ac)); } doRevokeGeneralApiKey(id, ac = mac()) { return this.doDelete(`api-key/${id}`, mri(ac)); } doRevokeApiKey(feed, id, ac = mac()) { if (feed === "*") { return this.doRevokeGeneralApiKey(id, ac); } else { return this.doRevokeFeedApiKey(feed, id, ac); } } doRevokeFeedApiKey(feed, id, ac = mac()) { return this.doDelete(`feed/${feed}/api-keys/${id}`, mri(ac)); } doDeletePilet(feed, id, all = false, ac = mac()) { return this.doDelete(`feed/${feed}/pilets/${id}?all=${all}`, mri(ac)); } doDeleteFeature(feed, id, ac = mac()) { return this.doDelete(`feed/${feed}/features/${id}`, mri(ac)); } doDeleteRule(feed, id, ac = mac()) { return this.doDelete(`feed/${feed}/rules/${id}`, mri(ac)); } doUpdateFeature(feed, id, content, ac = mac()) { return this.doPut(`feed/${feed}/features/${id}`, content, mri(ac)); } doUpdateRule(feed, id, content, ac = mac()) { return this.doPut(`feed/${feed}/rules/${id}`, content, mri(ac)); } doUpdatePilet(feed, id, content, tag = "latest", ac = mac()) { return this.doPut(`feed/${feed}/pilets/${id}?tag=${tag}`, content, mri(ac)); } doUpdateFeed(feed, content, ac = mac()) { return this.doPut(`feed/${feed}`, content, mri(ac)); } doUpdateApiKey(feed, id, content, ac = mac()) { if (feed === "*") { return this.doUpdateGeneralApiKey(id, content, ac); } else { return this.doUpdateFeedApiKey(feed, id, content, ac); } } doUpdateFeedApiKey(feed, id, content, ac = mac()) { return this.doPut(`feed/${feed}/api-keys/${id}`, content, mri(ac)); } doUpdateGeneralApiKey(id, content, ac = mac()) { return this.doPut(`api-key/${id}`, content, mri(ac)); } doQueryAudits(offset = "", count = "20", areaName = "", areaId = "", objectId = "", userId = "", q, ac = mac(), start, end) { const queryString = makeQueryString({ offset, count, areaName, areaId, objectId, userId, q, start, end }); return this.doGet(`audit?${queryString}`, mri(ac)); } doQueryAudit(id, ac = mac()) { return this.doGet(`audit/${id}`, mri(ac)); } doQueryAllUsers(q, offset, count, ac = mac()) { const queryString = makeQueryString({ q, offset, count }); return this.doGet(`query-users?${queryString}`, mri(ac)); } doQueryFeedContributors(feed, ac = mac()) { return this.doGet(`feed/${feed}/contributors`, mri(ac)); } doPutFeedContributors(feed, content, ac = mac()) { return this.doPut(`feed/${feed}/contributors`, content, mri(ac)); } doQueryFeedTags(feed, ac = mac()) { return this.doGet(`feed/${feed}/tags`, mri(ac)); } doDeleteFeedTag(feed, tag, ac = mac()) { return this.doDelete(`feed/${feed}/tags/${tag}`, mri(ac)); } doQueryConfigs(feed, pilet, ac = mac()) { return this.doGet(`feed/${feed}/pilets/${pilet}/configs`, mri(ac)); } doQueryConfig(feed, pilet, config, ac = mac()) { return this.doGet(`feed/${feed}/pilets/${pilet}/configs/${config}`, mri(ac)); } doAddConfig(feed, pilet, content, ac = mac()) { return this.doPost(`feed/${feed}/pilets/${pilet}/configs`, content, mri(ac)); } doDeleteConfig(feed, pilet, config, ac = mac()) { return this.doDelete(`feed/${feed}/pilets/${pilet}/configs/${config}`, mri(ac)); } doUpdateConfig(feed, pilet, config, content, ac = mac()) { return this.doPut(`feed/${feed}/pilets/${pilet}/configs/${config}`, content, mri(ac)); } doQueryAllFeedConfigs(feed, ac = mac()) { return this.doGet(`feed/${feed}/configs`, mri(ac)); } doQueryFeedConfigs(feed, configId, ac = mac()) { return this.doGet(`feed/${feed}/configs/${configId}`, mri(ac)); } doQueryFeedConfig(feed, configId, config, ac = mac()) { return this.doGet(`feed/${feed}/configs/${configId}/${config}`, mri(ac)); } doAddFeedConfig(feed, configId, content, ac = mac()) { return this.doPost(`feed/${feed}/configs/${configId}`, content, mri(ac)); } doDeleteFeedConfig(feed, configId, config, ac = mac()) { return this.doDelete(`feed/${feed}/configs/${configId}/${config}`, mri(ac)); } doUpdateFeedConfig(feed, configId, config, content, ac = mac()) { return this.doPut(`feed/${feed}/configs/${configId}/${config}`, content, mri(ac)); } doQueryEntities(feed, ac = mac()) { return this.doGet(`feed/${feed}/entities`, mri(ac)); } doQueryEntity(feed, id, ac = mac()) { return this.doGet(`feed/${feed}/entities/${id}`, mri(ac)); } doAddEntity(feed, content, ac = mac()) { return this.doPost(`feed/${feed}/entities`, content, mri(ac)); } doDeleteEntity(feed, id, ac = mac()) { return this.doDelete(`feed/${feed}/entities/${id}`, mri(ac)); } doUpdateEntity(feed, id, content, ac = mac()) { return this.doPut(`feed/${feed}/entities/${id}`, content, mri(ac)); } doQueryExternalUsers(q, offset, count, ac = mac()) { const queryString = makeQueryString({ q, offset, count }); return this.doGet(`external-users?${queryString}`, mri(ac)); } doQueryUsers(ac = mac()) { return this.doGet(`user`, mri(ac)); } doQueryUser(id, ac = mac()) { return this.doGet(`user/${id}`, mri(ac)); } doAddUser(content, ac = mac()) { return this.doPost(`user`, content, mri(ac)); } doDeleteUser(id, ac = mac()) { return this.doDelete(`user/${id}`, mri(ac)); } doUpdateUser(id, content, ac = mac()) { return this.doPut(`user/${id}`, content, mri(ac)); } doQueryCustomRules(ac = mac()) { return this.doGet(`customrule`, mri(ac)); } doQueryGroups(ac = mac()) { return this.doGet(`group`, mri(ac)); } doQueryGroup(id, ac = mac()) { return this.doGet(`group/${id}`, mri(ac)); } doAddGroup(content, ac = mac()) { return this.doPost(`group`, content, mri(ac)); } doUpdateGroup(id, content, ac = mac()) { return this.doPut(`group/${id}`, content, mri(ac)); } doDeleteGroup(id, ac = mac()) { return this.doDelete(`group/${id}`, mri(ac)); } doAddCustomRules(file, content, ac = mac()) { return this.doPost(`customrule`, { file, content }, mri(ac)); } doDeleteCustomRule(file, ac = mac()) { return this.doDelete(`customrule/${file}`, mri(ac)); } doQueryCustomRuleDetails(file, ac = mac()) { return this.doGet(`customrule/${file}`, mri(ac)); } doTestRule(feed, rule, content, ac = mac()) { return this.doPost(`feed/${feed}/rules/${rule}/test`, content, mri(ac)); } doQueryCurrentUser(ac = mac()) { return this.doGet(`current-user`, mri(ac)); } doUpdateCurrentUser(content, ac = mac()) { return this.doPut(`current-user`, content, mri(ac)); } doQueryStatus(ac = mac()) { return fetchWithoutToken(this.http, this.getUrl("status"), mri(ac)).then((res) => res.json()); } doQueryStatistics(ac = mac()) { return fetchWithoutToken(this.http, this.getUrl("statistics"), mri(ac)).then((res) => res.json()); } doQueryRulesSchema(ac = mac()) { return fetchWithoutToken(this.http, this.getUrl("schema/rule"), mri(ac)).then((res) => res.json()); } doQueryFeedAnalysis(feed, ac = mac()) { return this.doGet(`feed/${feed}/analysis`, mri(ac)); } doQueryPiletAnalysis(feed, id, ac = mac()) { return this.doGet(`feed/${feed}/analysis/${id}`, mri(ac)); } doQueryFeedVulnerabiltiyAnalysis(feed, ac = mac()) { return this.doGet(`feed/${feed}/vulnerabilities`, mri(ac)); } doTriggerVulnerabilityAnalysis(feed, ac = mac()) { return this.doPost(`feed/${feed}/vulnerabilities`, {}, mri(ac)); } doRecheckDomains(feed, domains, ac = mac()) { return this.doPut(`feed/${feed}/domains`, { domains }, mri(ac)); } doQueryFeedStatistics(feed, from, to, ac = mac()) { const queryString = makeQueryString({ from, to }); return this.doGet(`feed/${feed}/statistics?${queryString}`, mri(ac)); } doQueryAdminFeedStatistics(offset = "", count = "40", ac = mac()) { const queryString = makeQueryString({ offset, count }); return this.doGet(`statistics/feed?${queryString}`, mri(ac)); } doQueryAdminFeedStatisticsDetails(feed, from, to, ac = mac()) { const queryString = makeQueryString({ from, to }); return this.doGet(`statistics/feed/${feed}?${queryString}`, mri(ac)); } doQueryNpmRegistry(feed, ac = mac()) { return this.doGet(`registry/${feed}`, mri(ac)); } doQueryNpmPackage(feed, name, ac = mac()) { return this.doGet(`registry/${feed}/${name}`, mri(ac)); } doUploadNpmPackage(feed, name, body, ac = mac()) { return this.doPut(`registry/${feed}/${name}`, body, mri(ac)); } doDownloadFile(fileUrl, ac = mac()) { return fetchWithToken(this.http, fileUrl, mri(ac)).then((res) => res.blob()); } doGetLicenseInfo(ac = mac()) { return this.doGet("license", mri(ac)); } doQueryPiletStorageEntries(feed, pilet, ac = mac()) { return this.doGet(`feed/${feed}/pilets/${pilet}/storage`, mri(ac)); } doAddPiletStorageEntry(feed, pilet, name, content, ac = mac()) { return this.doPost(`feed/${feed}/pilets/${pilet}/storage`, { name, content }, mri(ac)); } doQueryPiletStorageEntry(feed, pilet, name, ac = mac()) { return this.doGet(`feed/${feed}/pilets/${pilet}/storage/${name}`, mri(ac)); } doUpdatePiletStorageEntry(feed, pilet, name, details, ac = mac()) { return this.doPut(`feed/${feed}/pilets/${pilet}/storage/${name}`, details, mri(ac)); } doDeletePiletStorageEntry(feed, pilet, name, ac = mac()) { return this.doDelete(`feed/${feed}/pilets/${pilet}/storage/${name}`, mri(ac)); } doQueryGenerators(feed, ac = mac()) { return this.doGet(`feed/${feed}/generator`, mri(ac)); } doQueryGeneratorSteps(feed, generator, ac = mac()) { return this.doGet(`feed/${feed}/generator/${generator}`, mri(ac)); } doGeneratePilet(feed, generator, details, ac = mac()) { return this.doPost(`feed/${feed}/generator/${generator}`, details, mri(ac)); } doQueryAllGenerators(ac = mac()) { return this.doGet(`generator`, mri(ac)); } doCreateGenerator(details, ac = mac()) { return this.doPost(`generator`, details, mri(ac)); } doQueryGeneratorDetails(generatorId, ac = mac()) { return this.doGet(`generator/${generatorId}`, mri(ac)); } doDeleteGenerator(generatorId, ac = mac()) { return this.doDelete(`generator/${generatorId}`, mri(ac)); } doQueryDashboard(ac = mac()) { return this.doGet("dashboard", mri(ac)); } doQueryDashboardFeeds(offset = "", count = "40", ac = mac()) { const queryString = makeQueryString({ offset, count }); return this.doGet(`dashboard/feeds?${queryString}`, mri(ac)); } doSendNotification(details, ac = mac()) { return this.doPost(`dashboard/notifications`, details, mri(ac)); } doQueryIssues(ac = mac()) { return this.doGet("issue", mri(ac)); } doCreateIssue(details, ac = mac()) { return this.doPost("issue", details, mri(ac)); } }; // src/utils.ts function createKeyHandler(apiKeyType) { switch (apiKeyType) { case "basic": return (apiKey) => `Basic ${apiKey}`; case "bearer": return (apiKey) => `Bearer ${apiKey}`; default: return (apiKey) => apiKey; } } function createAuthHead(options) { if ("apiKey" in options) { const { apiKey } = options; if (typeof apiKey !== "string") { throw new Error('The field "apiKey" has to be of type string.'); } return () => Promise.resolve(`Basic ${apiKey}`); } else if ("resolveApiKey" in options) { const { resolveApiKey, apiKeyType = "basic" } = options; if (typeof options.resolveApiKey !== "function") { throw new Error('The field "resolveApiKey" has to be of type function.'); } if (typeof apiKeyType !== "string") { throw new Error('The field "apiKeyType" has to be of type string.'); } const makeKey = createKeyHandler(apiKeyType); return () => resolveApiKey().then(makeKey); } else { throw new Error('You must either specify "apikey" or "resolveApiKey".'); } } // src/index.ts function createServiceClient(options) { if (typeof options === "undefined") { throw new Error('No "options" provided to create the service client.'); } if (typeof options !== "object") { throw new Error('The "options" have to be an object containing an "apiKey" field.'); } const { host = "https://feed.piral.cloud", defaults = {} } = options; if (typeof host !== "string") { throw new Error('The field "host" has to be of type string.'); } const getAuthorizationHeader = createAuthHead(options); const fetch = window.fetch.bind(window); const http = { fetch, FormData, Headers, getAuthorizationHeader, defaults }; return new FeedServiceApiClient(http, host); } export { createServiceClient };