Merge pull request #27950 from backstage/freben/no-node-fetch

remove most usages of node-fetch
This commit is contained in:
Fredrik Adelöw
2024-12-02 11:49:26 +01:00
committed by GitHub
99 changed files with 270 additions and 290 deletions
+41
View File
@@ -0,0 +1,41 @@
---
'@backstage/plugin-auth-backend-module-cloudflare-access-provider': patch
'@backstage/plugin-auth-backend-module-bitbucket-server-provider': patch
'@backstage/plugin-search-backend-module-stack-overflow-collator': patch
'@backstage/plugin-scaffolder-backend-module-bitbucket-server': patch
'@backstage/plugin-scaffolder-backend-module-bitbucket-cloud': patch
'@backstage/plugin-catalog-backend-module-bitbucket-server': patch
'@backstage/plugin-auth-backend-module-microsoft-provider': patch
'@backstage/plugin-auth-backend-module-aws-alb-provider': patch
'@backstage/plugin-scaffolder-backend-module-bitbucket': patch
'@backstage/plugin-scaffolder-backend-module-gerrit': patch
'@backstage/plugin-scaffolder-backend-module-sentry': patch
'@backstage/plugin-catalog-backend-module-puppetdb': patch
'@backstage/plugin-scaffolder-backend-module-gitea': patch
'@backstage/plugin-catalog-backend-module-msgraph': patch
'@backstage/plugin-search-backend-module-techdocs': patch
'@backstage/plugin-catalog-backend-module-gerrit': patch
'@backstage/plugin-catalog-backend-module-gitlab': patch
'@backstage/plugin-search-backend-module-explore': patch
'@backstage/plugin-catalog-backend-module-azure': patch
'@backstage/plugin-notifications-backend': patch
'@backstage/plugin-notifications-node': patch
'@backstage/plugin-permission-backend': patch
'@backstage/backend-app-api': patch
'@backstage/plugin-devtools-backend': patch
'@backstage/plugin-techdocs-backend': patch
'@backstage/plugin-catalog-backend': patch
'@backstage/plugin-signals-backend': patch
'@backstage/config-loader': patch
'@backstage/plugin-proxy-backend': patch
'@backstage/plugin-auth-backend': patch
'@backstage/create-app': patch
'@backstage/plugin-app-backend': patch
'@backstage/plugin-auth-node': patch
'@backstage/cli': patch
'@backstage/backend-defaults': patch
'@backstage/plugin-catalog-backend-module-github': patch
'@backstage/plugin-scaffolder-backend-module-confluence-to-markdown': patch
---
Use native fetch instead of node-fetch
@@ -26,7 +26,6 @@ import { readFile, writeFile } from 'node:fs/promises';
import { gzipSync } from 'node:zlib';
import { ensureDir } from 'fs-extra';
import { program } from 'commander';
import fetch from 'node-fetch';
import ora from 'ora';
import readdir from 'recursive-readdir';
import { parse } from 'yaml';
@@ -16,7 +16,6 @@ import {
coreServices,
createBackendPlugin,
} from '@backstage/backend-plugin-api';
import { fetch } from 'node-fetch';
createBackendPlugin({
pluginId: 'example',
@@ -16,7 +16,6 @@ import {
coreServices,
createBackendPlugin,
} from '@backstage/backend-plugin-api';
import { fetch } from 'node-fetch';
createBackendPlugin({
pluginId: 'example',
@@ -106,15 +106,12 @@ Imagine your FAQs can be retrieved at the URL `https://backstage.example.biz/faq
Below we provide an example implementation of how the FAQ collator factory could look like using our new document type, placed in the `plugins/search-backend-module-faq-snippets-collator/src/factory.ts` file:
```ts
import fetch from 'node-fetch';
import { Readable } from 'stream';
import {
LoggerService,
RootConfigService,
} from '@backstage/backend-plugin-api';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { FaqSnippetDocument } from './types';
const DEFAULT_BASE_URL = 'https://backstage.example.biz/faq-snippets';
+3 -3
View File
@@ -49,9 +49,9 @@
"storybook": "yarn ./storybook run storybook",
"techdocs-cli": "node scripts/techdocs-cli.js",
"techdocs-cli:dev": "cross-env TECHDOCS_CLI_DEV_MODE=true node scripts/techdocs-cli.js",
"test": "backstage-cli repo test",
"test:all": "backstage-cli repo test --coverage",
"test:e2e": "playwright test",
"test": "NODE_OPTIONS=--no-node-snapshot backstage-cli repo test",
"test:all": "NODE_OPTIONS=--no-node-snapshot backstage-cli repo test --coverage",
"test:e2e": "NODE_OPTIONS=--no-node-snapshot playwright test",
"tsc": "tsc",
"tsc:full": "backstage-cli repo clean && tsc --skipLibCheck false --incremental false"
},
-1
View File
@@ -71,7 +71,6 @@
"minimatch": "^9.0.0",
"minimist": "^1.2.5",
"morgan": "^1.10.0",
"node-fetch": "^2.7.0",
"node-forge": "^1.3.1",
"path-to-regexp": "^8.0.0",
"selfsigned": "^2.0.0",
@@ -415,17 +415,29 @@ export interface ReadTreeResponseFactory {
}
// @public
export type ReadTreeResponseFactoryOptions = {
stream: Readable;
subpath?: string;
etag: string;
filter?: (
path: string,
info?: {
size: number;
},
) => boolean;
};
export type ReadTreeResponseFactoryOptions =
| {
stream: Readable;
subpath?: string;
etag: string;
filter?: (
path: string,
info?: {
size: number;
},
) => boolean;
}
| {
response: Response;
subpath?: string;
etag?: string;
filter?: (
path: string,
info?: {
size: number;
},
) => boolean;
};
// @public
export class ReadUrlResponseFactory {
@@ -437,6 +449,9 @@ export class ReadUrlResponseFactory {
stream: Readable,
options?: ReadUrlResponseFactoryFromStreamOptions,
): Promise<UrlReaderServiceReadUrlResponse>;
static fromResponse(
response: Response,
): Promise<UrlReaderServiceReadUrlResponse>;
}
// @public
@@ -32,9 +32,7 @@ import {
ScmIntegrations,
AzureIntegration,
} from '@backstage/integration';
import fetch, { Response } from 'node-fetch';
import { Minimatch } from 'minimatch';
import { Readable } from 'stream';
import { NotFoundError, NotModifiedError } from '@backstage/errors';
import { ReadTreeResponseFactory, ReaderFactory } from './types';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
@@ -101,7 +99,7 @@ export class AzureUrlReader implements UrlReaderService {
// for private repos when PAT is not valid, Azure API returns a http status code 203 with sign in page html
if (response.ok && response.status !== 203) {
return ReadUrlResponseFactory.fromNodeJSReadable(response.body);
return ReadUrlResponseFactory.fromResponse(response);
}
const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`;
@@ -172,7 +170,7 @@ export class AzureUrlReader implements UrlReaderService {
}
return await this.deps.treeResponseFactory.fromZipArchive({
stream: Readable.from(archiveAzureResponse.body),
response: archiveAzureResponse,
etag: commitSha,
filter,
subpath,
@@ -32,14 +32,11 @@ import {
getBitbucketCloudRequestOptions,
ScmIntegrations,
} from '@backstage/integration';
import fetch, { Response } from 'node-fetch';
import parseGitUrl from 'git-url-parse';
import { trimEnd } from 'lodash';
import { Minimatch } from 'minimatch';
import { Readable } from 'stream';
import { ReaderFactory, ReadTreeResponseFactory } from './types';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
import { parseLastModified } from './util';
/**
* Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files from Bitbucket Cloud.
@@ -116,12 +113,7 @@ export class BitbucketCloudUrlReader implements UrlReaderService {
}
if (response.ok) {
return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {
etag: response.headers.get('ETag') ?? undefined,
lastModifiedAt: parseLastModified(
response.headers.get('Last-Modified'),
),
});
return ReadUrlResponseFactory.fromResponse(response);
}
const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;
@@ -159,7 +151,7 @@ export class BitbucketCloudUrlReader implements UrlReaderService {
}
return await this.deps.treeResponseFactory.fromTarArchive({
stream: Readable.from(archiveResponse.body),
response: archiveResponse,
subpath: filepath,
etag: lastCommitShortHash,
filter: options?.filter,
@@ -31,14 +31,11 @@ import {
getBitbucketServerRequestOptions,
ScmIntegrations,
} from '@backstage/integration';
import fetch, { Response } from 'node-fetch';
import parseGitUrl from 'git-url-parse';
import { trimEnd } from 'lodash';
import { Minimatch } from 'minimatch';
import { Readable } from 'stream';
import { ReaderFactory, ReadTreeResponseFactory } from './types';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
import { parseLastModified } from './util';
/**
* Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files from Bitbucket Server APIs.
@@ -107,12 +104,7 @@ export class BitbucketServerUrlReader implements UrlReaderService {
}
if (response.ok) {
return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {
etag: response.headers.get('ETag') ?? undefined,
lastModifiedAt: parseLastModified(
response.headers.get('Last-Modified'),
),
});
return ReadUrlResponseFactory.fromResponse(response);
}
const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;
@@ -150,7 +142,7 @@ export class BitbucketServerUrlReader implements UrlReaderService {
}
return await this.deps.treeResponseFactory.fromTarArchive({
stream: Readable.from(archiveResponse.body),
response: archiveResponse,
subpath: filepath,
etag: lastCommitShortHash,
filter: options?.filter,
@@ -32,15 +32,12 @@ import {
getBitbucketRequestOptions,
ScmIntegrations,
} from '@backstage/integration';
import fetch, { Response } from 'node-fetch';
import parseGitUrl from 'git-url-parse';
import { trimEnd } from 'lodash';
import { Minimatch } from 'minimatch';
import { Readable } from 'stream';
import { LoggerService } from '@backstage/backend-plugin-api';
import { ReaderFactory, ReadTreeResponseFactory } from './types';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
import { parseLastModified } from './util';
/**
* Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files from Bitbucket v1 and v2 APIs, such
@@ -127,12 +124,7 @@ export class BitbucketUrlReader implements UrlReaderService {
}
if (response.ok) {
return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {
etag: response.headers.get('ETag') ?? undefined,
lastModifiedAt: parseLastModified(
response.headers.get('Last-Modified'),
),
});
return ReadUrlResponseFactory.fromResponse(response);
}
const message = `${url} could not be read as ${bitbucketUrl}, ${response.status} ${response.statusText}`;
@@ -170,7 +162,7 @@ export class BitbucketUrlReader implements UrlReaderService {
}
return await this.deps.treeResponseFactory.fromTarArchive({
stream: Readable.from(archiveBitbucketResponse.body),
response: archiveBitbucketResponse,
subpath: filepath,
etag: lastCommitShortHash,
filter: options?.filter,
@@ -22,11 +22,9 @@ import {
UrlReaderServiceSearchResponse,
} from '@backstage/backend-plugin-api';
import { NotFoundError, NotModifiedError } from '@backstage/errors';
import fetch, { Response } from 'node-fetch';
import { ReaderFactory } from './types';
import path from 'path';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
import { parseLastModified } from './util';
const isInRange = (num: number, [start, end]: [number, number]) => {
return num >= start && num <= end;
@@ -150,12 +148,7 @@ export class FetchUrlReader implements UrlReaderService {
}
if (response.ok) {
return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {
etag: response.headers.get('ETag') ?? undefined,
lastModifiedAt: parseLastModified(
response.headers.get('Last-Modified'),
),
});
return ReadUrlResponseFactory.fromResponse(response);
}
const message = `could not read ${url}, ${response.status} ${response.statusText}`;
@@ -32,7 +32,6 @@ import {
ScmIntegrations,
} from '@backstage/integration';
import { ReaderFactory, ReadTreeResponseFactory } from './types';
import fetch, { Response } from 'node-fetch';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
import {
AuthenticationError,
@@ -149,7 +148,7 @@ export class GiteaUrlReader implements UrlReaderService {
const parsedUri = parseGiteaUrl(this.integration.config, url);
return this.deps.treeResponseFactory.fromTarArchive({
stream: Readable.from(response.body),
response: response,
subpath: parsedUri.path,
etag: lastCommitHash,
filter: options?.filter,
@@ -34,11 +34,8 @@ import {
import parseGitUrl from 'git-url-parse';
import { trimEnd, trimStart } from 'lodash';
import { Minimatch } from 'minimatch';
import fetch, { Response } from 'node-fetch';
import { Readable } from 'stream';
import { ReadUrlResponseFactory } from './ReadUrlResponseFactory';
import { ReadTreeResponseFactory, ReaderFactory } from './types';
import { parseLastModified } from './util';
/**
* Implements a {@link @backstage/backend-plugin-api#UrlReaderService} for files on GitLab.
@@ -101,12 +98,7 @@ export class GitlabUrlReader implements UrlReaderService {
}
if (response.ok) {
return ReadUrlResponseFactory.fromNodeJSReadable(response.body, {
etag: response.headers.get('ETag') ?? undefined,
lastModifiedAt: parseLastModified(
response.headers.get('Last-Modified'),
),
});
return ReadUrlResponseFactory.fromResponse(response);
}
const message = `${url} could not be read as ${builtUrl}, ${response.status} ${response.statusText}`;
@@ -228,7 +220,7 @@ export class GitlabUrlReader implements UrlReaderService {
}
return await this.deps.treeResponseFactory.fromTarArchive({
stream: Readable.from(archiveGitLabResponse.body),
response: archiveGitLabResponse,
subpath: filepath,
etag: commitSha,
filter: options?.filter,
@@ -19,6 +19,7 @@ import { UrlReaderServiceReadUrlResponse } from '@backstage/backend-plugin-api';
import getRawBody from 'raw-body';
import { Readable } from 'stream';
import { ReadUrlResponseFactoryFromStreamOptions } from './types';
import { parseLastModified, responseToReadable } from './util';
/**
* Utility class for UrlReader implementations to create valid ReadUrlResponse
@@ -28,7 +29,7 @@ import { ReadUrlResponseFactoryFromStreamOptions } from './types';
*/
export class ReadUrlResponseFactory {
/**
* Resolves a ReadUrlResponse from a Readable stream.
* Resolves a UrlReaderServiceReadUrlResponse from a Readable stream.
*/
static async fromReadable(
stream: Readable,
@@ -64,7 +65,7 @@ export class ReadUrlResponseFactory {
}
/**
* Resolves a ReadUrlResponse from an old-style NodeJS.ReadableStream.
* Resolves a UrlReaderServiceReadUrlResponse from an old-style NodeJS.ReadableStream.
*/
static async fromNodeJSReadable(
oldStyleStream: NodeJS.ReadableStream,
@@ -73,4 +74,21 @@ export class ReadUrlResponseFactory {
const readable = Readable.from(oldStyleStream);
return ReadUrlResponseFactory.fromReadable(readable, options);
}
/**
* Resolves a UrlReaderServiceReadUrlResponse from a native fetch response body.
*/
static async fromResponse(
response: Response,
): Promise<UrlReaderServiceReadUrlResponse> {
const etag = response.headers.get('etag') || undefined;
const lastModifiedAt = parseLastModified(
response.headers.get('last-modified'),
);
return ReadUrlResponseFactory.fromReadable(responseToReadable(response), {
etag,
lastModifiedAt,
});
}
}
@@ -15,6 +15,7 @@
*/
import os from 'os';
import { Readable } from 'stream';
import { Config } from '@backstage/config';
import {
ReadTreeResponseFactoryOptions,
@@ -25,6 +26,7 @@ import { TarArchiveResponse } from './TarArchiveResponse';
import { ZipArchiveResponse } from './ZipArchiveResponse';
import { ReadableArrayResponse } from './ReadableArrayResponse';
import { UrlReaderServiceReadTreeResponse } from '@backstage/backend-plugin-api';
import { responseToReadable } from '../util';
export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {
static create(options: { config: Config }): DefaultReadTreeResponseFactory {
@@ -41,11 +43,21 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {
stripFirstDirectory?: boolean;
},
): Promise<UrlReaderServiceReadTreeResponse> {
let stream: Readable;
let etag: string;
if ('stream' in options) {
stream = options.stream;
etag = options.etag;
} else {
stream = responseToReadable(options.response);
etag = (options.etag ?? options.response.headers.get('etag')) || '';
}
return new TarArchiveResponse(
options.stream,
stream,
options.subpath ?? '',
this.workDir,
options.etag,
etag,
options.filter,
options.stripFirstDirectory ?? true,
);
@@ -54,11 +66,21 @@ export class DefaultReadTreeResponseFactory implements ReadTreeResponseFactory {
async fromZipArchive(
options: ReadTreeResponseFactoryOptions,
): Promise<UrlReaderServiceReadTreeResponse> {
let stream: Readable;
let etag: string;
if ('stream' in options) {
stream = options.stream;
etag = options.etag;
} else {
stream = responseToReadable(options.response);
etag = (options.etag ?? options.response.headers.get('etag')) || '';
}
return new ZipArchiveResponse(
options.stream,
stream,
options.subpath ?? '',
this.workDir,
options.etag,
etag,
options.filter,
);
}
@@ -60,17 +60,28 @@ export type ReadUrlResponseFactoryFromStreamOptions = {
*
* @public
*/
export type ReadTreeResponseFactoryOptions = {
// A binary stream of a tar archive.
stream: Readable;
// If unset, the files at the root of the tree will be read.
// subpath must not contain the name of the top level directory.
subpath?: string;
// etag of the blob
etag: string;
// Filter passed on from the ReadTreeOptions
filter?: (path: string, info?: { size: number }) => boolean;
};
export type ReadTreeResponseFactoryOptions =
| {
// A binary stream of a tar archive.
stream: Readable;
// If unset, the files at the root of the tree will be read.
// subpath must not contain the name of the top level directory.
subpath?: string;
// etag of the blob
etag: string;
// Filter passed on from the ReadTreeOptions
filter?: (path: string, info?: { size: number }) => boolean;
}
| {
/** A response from a fetch request */
response: Response;
/** If unset, the files at the root of the tree will be read. Subpath must not contain the name of the top level directory. */
subpath?: string;
/** etag of the blob, to optionally override what the response header may or may not say */
etag?: string;
/** Filter passed on from the ReadTreeOptions */
filter?: (path: string, info?: { size: number }) => boolean;
};
/**
* Options that control {@link ReadTreeResponseFactory.fromReadableArray}
@@ -14,10 +14,47 @@
* limitations under the License.
*/
export function parseLastModified(value: string | null | undefined) {
import { PassThrough, Readable } from 'stream';
import { ReadableStream as WebReadableStream } from 'stream/web';
export function parseLastModified(
value: string | null | undefined,
): Date | undefined {
if (!value) {
return undefined;
}
return new Date(value);
try {
const result = new Date(value);
result.toISOString(); // triggers exception if input was invalid
return result;
} catch {
return undefined;
}
}
export function responseToReadable(response: Response): Readable {
return response.body
? Readable.from(toWeb(response.body))
: new PassThrough().end();
}
// The NodeJS ReadableStream is that fetch returns is super basic and not even
// iterable. This function converts it to the smarter, iterable stream/web
// variant instead.
export function toWeb(
responseBody: ReadableStream<Uint8Array>,
): WebReadableStream<Uint8Array> {
const reader = responseBody.getReader();
return new WebReadableStream({
async pull(controller) {
const { value, done } = await reader.read();
if (value) {
controller.enqueue(value);
}
if (done) {
controller.close();
}
},
});
}
@@ -22,7 +22,6 @@ import {
} from '@backstage/backend-plugin-api';
import { ResponseError } from '@backstage/errors';
import { decodeJwt } from 'jose';
import fetch from 'node-fetch';
import { toInternalBackstageCredentials } from '../auth/helpers';
export type Options = {
-1
View File
@@ -122,7 +122,6 @@
"lodash": "^4.17.21",
"mini-css-extract-plugin": "^2.4.2",
"minimatch": "^9.0.0",
"node-fetch": "^2.7.0",
"node-libs-browser": "^2.2.1",
"npm-packlist": "^5.0.0",
"ora": "^5.3.0",
@@ -20,7 +20,6 @@ import { stringify as stringifyYaml } from 'yaml';
import inquirer, { Question, Answers } from 'inquirer';
import { paths } from '../../lib/paths';
import { GithubCreateAppServer } from './GithubCreateAppServer';
import fetch from 'node-fetch';
import openBrowser from 'react-dev-utils/openBrowser';
// This is an experimental command that at this point does not support GitHub Enterprise
-1
View File
@@ -49,7 +49,6 @@
"json-schema-traverse": "^1.0.0",
"lodash": "^4.17.21",
"minimist": "^1.2.5",
"node-fetch": "^2.7.0",
"typescript-json-schema": "^0.65.0",
"yaml": "^2.0.0"
},
@@ -21,7 +21,6 @@ import {
durationToMilliseconds,
} from '@backstage/types';
import isEqual from 'lodash/isEqual';
import fetch from 'node-fetch';
import { ConfigTransformer, createConfigTransformer } from './transform';
import {
AsyncConfigSourceGenerator,
@@ -137,7 +136,7 @@ export class RemoteConfigSource implements ConfigSource {
async #load(signal?: AbortSignal): Promise<JsonObject> {
const res = await fetch(this.#url, {
signal: signal as import('node-fetch').RequestInit['signal'],
signal: signal as RequestInit['signal'],
});
if (!res.ok) {
throw await ResponseError.fromResponse(res);
+1 -2
View File
@@ -49,7 +49,6 @@
"fs-extra": "^11.2.0",
"handlebars": "^4.7.3",
"inquirer": "^8.2.0",
"node-fetch": "^2.7.0",
"ora": "^5.3.0",
"recursive-readdir": "^2.2.2"
},
@@ -61,7 +60,7 @@
"@types/inquirer": "^8.1.3",
"@types/node": "^20.16.0",
"@types/recursive-readdir": "^2.2.0",
"msw": "^1.0.0",
"msw": "^2.0.0",
"nodemon": "^3.0.1"
}
}
+8 -11
View File
@@ -33,7 +33,7 @@ import {
createMockDirectory,
registerMswTestHooks,
} from '@backstage/backend-test-utils';
import { rest } from 'msw';
import { http, HttpResponse, delay } from 'msw';
import { setupServer } from 'msw/node';
jest.spyOn(Task, 'log').mockReturnValue(undefined);
@@ -402,12 +402,10 @@ describe('tasks', () => {
it('should fetch the yarn.lock seed file', async () => {
worker.use(
rest.get(
http.get(
'https://raw.githubusercontent.com/backstage/backstage/master/packages/create-app/seed-yarn.lock',
(_, res, ctx) =>
res(
ctx.status(200),
ctx.text(`# the-lockfile-header
() =>
HttpResponse.text(`# the-lockfile-header
// some comments
// in the file
@@ -418,7 +416,6 @@ describe('tasks', () => {
"@backstage/cli@1.0.0":
some info
`),
),
),
);
@@ -438,9 +435,9 @@ describe('tasks', () => {
it('should fail gracefully', async () => {
worker.use(
rest.get(
http.get(
'https://raw.githubusercontent.com/backstage/backstage/master/packages/create-app/seed-yarn.lock',
(_, res, ctx) => res(ctx.status(404)),
() => new HttpResponse(null, { status: 404 }),
),
);
@@ -453,9 +450,9 @@ describe('tasks', () => {
it('should time out if it takes too long to fetch', async () => {
worker.use(
rest.get(
http.get(
'https://raw.githubusercontent.com/backstage/backstage/master/packages/create-app/seed-yarn.lock',
(_, res, ctx) => res(ctx.delay(5000)),
() => delay(5000),
),
);
-1
View File
@@ -25,7 +25,6 @@ import {
resolve as resolvePath,
relative as relativePath,
} from 'path';
import fetch from 'node-fetch';
import { exec as execCb } from 'child_process';
import { packageVersions } from './versions';
import { promisify } from 'util';
-1
View File
@@ -83,7 +83,6 @@
"@backstage/cli": "workspace:^",
"@backstage/types": "workspace:^",
"@types/supertest": "^2.0.8",
"node-fetch": "^2.7.0",
"supertest": "^7.0.0"
},
"configSchema": "config.d.ts"
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import fetch from 'node-fetch';
import {
createMockDirectory,
mockServices,
@@ -42,8 +42,7 @@
"@backstage/plugin-auth-backend": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
"jose": "^5.0.0",
"node-cache": "^5.1.2",
"node-fetch": "^2.7.0"
"node-cache": "^5.1.2"
},
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
@@ -13,11 +13,11 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { KeyObject } from 'crypto';
import * as crypto from 'crypto';
import { JWTHeaderParameters, decodeJwt } from 'jose';
import NodeCache from 'node-cache';
import fetch from 'node-fetch';
import { PassportProfile, ProfileInfo } from '@backstage/plugin-auth-node';
import { AuthenticationError } from '@backstage/errors';
@@ -36,7 +36,6 @@
"dependencies": {
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
"node-fetch": "^2.7.0",
"passport": "^0.7.0",
"passport-oauth2": "^1.6.1"
},
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import fetch from 'node-fetch';
import { PassportProfile } from '@backstage/plugin-auth-node';
export async function fetchProfile(options: {
@@ -39,8 +39,7 @@
"@backstage/errors": "workspace:^",
"@backstage/plugin-auth-node": "workspace:^",
"express": "^4.18.2",
"jose": "^5.0.0",
"node-fetch": "^2.7.0"
"jose": "^5.0.0"
},
"devDependencies": {
"@backstage/backend-defaults": "workspace:^",
@@ -23,7 +23,6 @@ import {
} from '@backstage/errors';
import express from 'express';
import { createRemoteJWKSet, jwtVerify } from 'jose';
import fetch, { Headers } from 'node-fetch';
import {
CACHE_PREFIX,
CF_JWT_HEADER,
@@ -87,8 +86,7 @@ export class AuthHelper {
// Only throw if both are not provided by Cloudflare Access since either
// can be used.
throw new AuthenticationError(
`Missing ${this.jwtHeaderName} and
${this.authorizationCookieName} from Cloudflare Access`,
`Missing ${this.jwtHeaderName} and ${this.authorizationCookieName} from Cloudflare Access`,
);
}
@@ -38,7 +38,6 @@
"@backstage/plugin-auth-node": "workspace:^",
"express": "^4.18.2",
"jose": "^5.0.0",
"node-fetch": "^2.7.0",
"passport-microsoft": "^1.0.0"
},
"devDependencies": {
@@ -16,7 +16,6 @@
import { PassportProfile } from '@backstage/plugin-auth-node';
import { decodeJwt } from 'jose';
import fetch from 'node-fetch';
import { Strategy as MicrosoftStrategy } from 'passport-microsoft';
export class ExtendedMicrosoftStrategy extends MicrosoftStrategy {
@@ -103,9 +102,9 @@ export class ExtendedMicrosoftStrategy extends MicrosoftStrategy {
},
},
);
const data = await res.buffer();
const data = await res.arrayBuffer();
return `data:image/jpeg;base64,${data.toString('base64')}`;
return `data:image/jpeg;base64,${Buffer.from(data).toString('base64')}`;
} catch (error) {
return undefined;
}
-1
View File
@@ -89,7 +89,6 @@
"minimatch": "^9.0.0",
"morgan": "^1.10.0",
"node-cache": "^5.1.2",
"node-fetch": "^2.7.0",
"openid-client": "^5.2.1",
"passport": "^0.7.0",
"passport-auth0": "^1.4.3",
-1
View File
@@ -49,7 +49,6 @@
"express": "^4.17.1",
"jose": "^5.0.0",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"passport": "^0.7.0",
"winston": "^3.2.1",
"zod": "^3.22.4",
@@ -58,7 +58,6 @@
"@backstage/integration": "workspace:^",
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-catalog-node": "workspace:^",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import fetch from 'node-fetch';
import {
AzureDevOpsCredentialsProvider,
AzureIntegrationConfig,
@@ -56,8 +56,6 @@
"@backstage/errors": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-catalog-node": "workspace:^",
"@types/node-fetch": "^2.5.12",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -11,7 +11,6 @@ import { EntityProvider } from '@backstage/plugin-catalog-node';
import { EntityProviderConnection } from '@backstage/plugin-catalog-node';
import { LocationSpec } from '@backstage/plugin-catalog-node';
import { LoggerService } from '@backstage/backend-plugin-api';
import { Response as Response_2 } from 'node-fetch';
import { SchedulerService } from '@backstage/backend-plugin-api';
import { SchedulerServiceTaskRunner } from '@backstage/backend-plugin-api';
@@ -27,7 +26,7 @@ export class BitbucketServerClient {
projectKey: string;
repo: string;
path: string;
}): Promise<Response_2>;
}): Promise<Response>;
// (undocumented)
getRepository(options: {
projectKey: string;
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import fetch, { Request, Response } from 'node-fetch';
import {
BitbucketServerIntegrationConfig,
getBitbucketServerRequestOptions,
@@ -53,7 +53,6 @@
"@backstage/integration": "workspace:^",
"@backstage/plugin-catalog-node": "workspace:^",
"fs-extra": "^11.2.0",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -22,7 +22,6 @@ import {
LocationSpec,
locationSpecToLocationEntity,
} from '@backstage/plugin-catalog-node';
import fetch, { Response } from 'node-fetch';
import {
GerritIntegration,
getGerritProjectsApiUrl,
@@ -66,7 +66,6 @@
"git-url-parse": "^15.0.0",
"lodash": "^4.17.21",
"minimatch": "^9.0.0",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -74,7 +73,7 @@
"@backstage/cli": "workspace:^",
"@types/lodash": "^4.14.151",
"luxon": "^3.0.0",
"msw": "^1.0.0"
"msw": "^2.0.0"
},
"configSchema": "config.d.ts"
}
@@ -39,7 +39,7 @@ import {
mockServices,
} from '@backstage/backend-test-utils';
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { http, HttpResponse } from 'msw';
import { ConfigReader } from '@backstage/config';
const server = setupServer();
@@ -67,10 +67,9 @@ describe('GithubLocationAnalyzer', () => {
beforeEach(() => {
server.use(
rest.post('http://localhost:7007/locations', async (_, res, ctx) => {
return res(
ctx.status(201),
ctx.json({
http.post('http://localhost:7007/locations', () =>
HttpResponse.json(
{
location: 'test',
exists: false,
entities: [
@@ -100,9 +99,10 @@ describe('GithubLocationAnalyzer', () => {
},
},
],
}),
);
}),
},
{ status: 201 },
),
),
);
octokit.repos.get.mockResolvedValue({
@@ -17,7 +17,7 @@
import { registerMswTestHooks } from '@backstage/backend-test-utils';
import { GroupEntity, UserEntity } from '@backstage/catalog-model';
import { graphql as graphqlOctokit } from '@octokit/graphql';
import { graphql as graphqlMsw } from 'msw';
import { graphql as graphqlMsw, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
import { TeamTransformer, UserTransformer } from './defaultTransformers';
import {
@@ -33,14 +33,13 @@ import {
createRemoveEntitiesOperation,
createReplaceEntitiesOperation,
} from './github';
import fetch from 'node-fetch';
describe('github', () => {
const graphql = graphqlOctokit.defaults({ request: { fetch } });
const server = setupServer();
registerMswTestHooks(server);
const graphql = graphqlOctokit.defaults({});
describe('getOrganizationUsers using defaultUserMapper', () => {
it('reads members', async () => {
const input: QueryResponse = {
@@ -73,7 +72,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('users', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('users', () => HttpResponse.json({ data: input })),
);
await expect(
@@ -136,7 +135,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('users', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('users', () => HttpResponse.json({ data: input })),
);
await expect(
@@ -180,7 +179,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('users', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('users', () => HttpResponse.json({ data: input })),
);
const users = await getOrganizationUsers(
@@ -255,7 +254,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('teams', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('teams', () => HttpResponse.json({ data: input })),
);
await expect(getOrganizationTeams(graphql, 'a')).resolves.toEqual(output);
@@ -355,7 +354,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('teams', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('teams', () => HttpResponse.json({ data: input })),
);
await expect(
@@ -435,7 +434,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('teams', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('teams', () => HttpResponse.json({ data: input })),
);
const teams = await getOrganizationTeams(
@@ -471,7 +470,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('orgs', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('orgs', () => HttpResponse.json({ data: input })),
);
await expect(getOrganizationsFromUser(graphql, 'foo')).resolves.toEqual({
@@ -500,7 +499,7 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('members', (_req, res, ctx) => res(ctx.data(input))),
graphqlMsw.query('members', () => HttpResponse.json({ data: input })),
);
await expect(getTeamMembers(graphql, 'a', 'b')).resolves.toEqual(output);
@@ -587,8 +586,8 @@ describe('github', () => {
};
server.use(
graphqlMsw.query('repositories', (_req, res, ctx) =>
res(ctx.data(input)),
graphqlMsw.query('repositories', () =>
HttpResponse.json({ data: input }),
),
);
@@ -61,7 +61,6 @@
"@backstage/plugin-events-node": "workspace:^",
"@gitbeaker/rest": "^40.0.3",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -13,13 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
getGitLabRequestOptions,
GitLabIntegrationConfig,
} from '@backstage/integration';
import fetch from 'node-fetch';
import { LoggerService } from '@backstage/backend-plugin-api';
import {
GitLabDescendantGroupsResponse,
GitLabGroup,
@@ -58,9 +58,7 @@
"@backstage/plugin-catalog-common": "workspace:^",
"@backstage/plugin-catalog-node": "workspace:^",
"@microsoft/microsoft-graph-types": "^2.6.0",
"@types/node-fetch": "^2.5.12",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"p-limit": "^3.0.2",
"qs": "^6.9.4",
"uuid": "^11.0.0"
@@ -17,7 +17,6 @@ import { LoggerService } from '@backstage/backend-plugin-api';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
import { OrganizationTransformer as OrganizationTransformer_2 } from '@backstage/plugin-catalog-backend-module-msgraph';
import { ProviderConfigTransformer as ProviderConfigTransformer_2 } from '@backstage/plugin-catalog-backend-module-msgraph';
import { Response as Response_2 } from 'node-fetch';
import { SchedulerService } from '@backstage/backend-plugin-api';
import { SchedulerServiceTaskRunner } from '@backstage/backend-plugin-api';
import { SchedulerServiceTaskScheduleDefinition } from '@backstage/backend-plugin-api';
@@ -114,7 +113,7 @@ export class MicrosoftGraphClient {
path: string,
query?: ODataQuery,
headers?: Record<string, string>,
): Promise<Response_2>;
): Promise<Response>;
requestCollection<T>(
path: string,
query?: ODataQuery,
@@ -124,7 +123,7 @@ export class MicrosoftGraphClient {
url: string,
headers?: Record<string, string>,
retryCount?: number,
): Promise<Response_2>;
): Promise<Response>;
}
// @public
@@ -20,7 +20,6 @@ import {
ClientSecretCredential,
} from '@azure/identity';
import * as MicrosoftGraph from '@microsoft/microsoft-graph-types';
import fetch, { Response } from 'node-fetch';
import qs from 'qs';
import { MicrosoftGraphProviderConfig } from './config';
@@ -61,7 +61,6 @@
"@backstage/types": "workspace:^",
"lodash": "^4.17.21",
"luxon": "^3.0.0",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -18,7 +18,6 @@ import { PuppetDbEntityProviderConfig } from '../providers';
import { PuppetNode, ResourceTransformer } from './types';
import { ResourceEntity } from '@backstage/catalog-model';
import { defaultResourceTransformer } from './transformers';
import fetch from 'node-fetch';
import { ResponseError } from '@backstage/errors';
import { ENDPOINT_FACTSETS } from './constants';
import { LoggerService } from '@backstage/backend-plugin-api';
-1
View File
@@ -89,7 +89,6 @@
"lodash": "^4.17.21",
"luxon": "^3.0.0",
"minimatch": "^9.0.0",
"node-fetch": "^2.7.0",
"p-limit": "^3.0.2",
"prom-client": "^15.0.0",
"uuid": "^11.0.0",
-1
View File
@@ -55,7 +55,6 @@
"express-promise-router": "^4.1.0",
"fs-extra": "^11.0.0",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"ping": "^0.4.1",
"semver": "^7.5.3",
"yn": "^4.0.0"
@@ -24,9 +24,7 @@ import {
ExternalDependencyStatus,
PackageDependency,
} from '@backstage/plugin-devtools-common';
import { JsonObject } from '@backstage/types';
import fetch from 'node-fetch';
import { findPaths } from '@backstage/cli-common';
import { getPackages } from '@manypkg/get-packages';
import ping from 'ping';
@@ -53,7 +53,6 @@
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"knex": "^3.0.0",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0",
"winston": "^3.2.1",
"yn": "^4.0.0"
-1
View File
@@ -43,7 +43,6 @@
"@backstage/plugin-notifications-common": "workspace:^",
"@backstage/plugin-signals-node": "workspace:^",
"knex": "^3.0.0",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0"
},
"devDependencies": {
@@ -17,7 +17,6 @@
import { NotificationService } from './NotificationService';
import { AuthService, DiscoveryService } from '@backstage/backend-plugin-api';
import { NotificationPayload } from '@backstage/plugin-notifications-common';
import fetch from 'node-fetch';
/** @public */
export type NotificationServiceOptions = {
-1
View File
@@ -63,7 +63,6 @@
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"yn": "^4.0.0",
"zod": "^3.22.4"
},
@@ -14,7 +14,6 @@
* limitations under the License.
*/
import fetch from 'node-fetch';
import { z } from 'zod';
import {
AuthorizeResult,
+1 -2
View File
@@ -77,8 +77,7 @@
"@backstage/errors": "workspace:^",
"@types/http-proxy-middleware": "^1.0.0",
"@types/yup": "^0.32.0",
"msw": "^2.0.0",
"node-fetch": "^2.7.0"
"msw": "^2.0.0"
},
"configSchema": "config.d.ts"
}
@@ -29,7 +29,6 @@ import {
} from '@backstage/config-loader';
import { HttpResponse, http, passthrough } from 'msw';
import { setupServer } from 'msw/node';
import fetch from 'node-fetch';
// this test is stored in its own file to work around the mocked
// http-proxy-middleware module used in the main test file
@@ -25,7 +25,6 @@ import { ResponseError } from '@backstage/errors';
import { JsonObject } from '@backstage/types';
import { HttpResponse, http, passthrough } from 'msw';
import { setupServer } from 'msw/node';
import fetch from 'node-fetch';
// this test is stored in its own file to work around the mocked
// http-proxy-middleware module used in the main test file
@@ -49,7 +49,6 @@
"@backstage/plugin-bitbucket-cloud-common": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"fs-extra": "^11.2.0",
"node-fetch": "^2.7.0",
"yaml": "^2.0.0"
},
"devDependencies": {
@@ -22,7 +22,6 @@ import {
getRepoSourceDirectory,
parseRepoUrl,
} from '@backstage/plugin-scaffolder-node';
import fetch, { Response, RequestInit } from 'node-fetch';
import { Config } from '@backstage/config';
import { getAuthorizationHeader } from './helpers';
@@ -16,7 +16,6 @@
import { examples } from './bitbucketCloudPipelinesRun.examples';
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import fetch, { Response } from 'node-fetch';
import * as inputProps from './inputProperties';
import { ScmIntegrationRegistry } from '@backstage/integration';
import { getAuthorizationHeader } from './helpers';
@@ -24,7 +24,6 @@ import {
cloneRepo,
parseRepoUrl,
} from '@backstage/plugin-scaffolder-node';
import fetch, { RequestInit, Response } from 'node-fetch';
import { Config } from '@backstage/config';
import fs from 'fs-extra';
import { getAuthorizationHeader } from './helpers';
@@ -48,7 +48,6 @@
"@backstage/integration": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"fs-extra": "^11.2.0",
"node-fetch": "^2.7.0",
"yaml": "^2.0.0"
},
"devDependencies": {
@@ -25,7 +25,6 @@ import {
getRepoSourceDirectory,
parseRepoUrl,
} from '@backstage/plugin-scaffolder-node';
import fetch, { Response, RequestInit } from 'node-fetch';
import { Config } from '@backstage/config';
import { examples } from './bitbucketServer.examples';
@@ -27,7 +27,6 @@ import {
cloneRepo,
parseRepoUrl,
} from '@backstage/plugin-scaffolder-node';
import fetch, { RequestInit, Response } from 'node-fetch';
import { Config } from '@backstage/config';
import fs from 'fs-extra';
import { examples } from './bitbucketServerPullRequest.examples';
@@ -50,7 +50,6 @@
"@backstage/plugin-scaffolder-backend-module-bitbucket-server": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"fs-extra": "^11.2.0",
"node-fetch": "^2.7.0",
"yaml": "^2.0.0"
},
"devDependencies": {
@@ -25,7 +25,6 @@ import {
getRepoSourceDirectory,
parseRepoUrl,
} from '@backstage/plugin-scaffolder-node';
import fetch, { Response, RequestInit } from 'node-fetch';
import { Config } from '@backstage/config';
import { examples } from './bitbucket.examples';
@@ -53,7 +53,6 @@
"@backstage/plugin-scaffolder-node": "workspace:^",
"fs-extra": "^11.2.0",
"git-url-parse": "^15.0.0",
"node-fetch": "^2.7.0",
"node-html-markdown": "^1.3.0",
"yaml": "^2.0.0"
},
@@ -17,7 +17,7 @@
import { Config } from '@backstage/config';
import { ResponseError, ConflictError, InputError } from '@backstage/errors';
import fs from 'fs-extra';
import fetch, { Response } from 'node-fetch';
import { Readable } from 'stream';
interface Links {
webui: string;
@@ -164,7 +164,9 @@ export const getAndWriteAttachments = async (
const writeStream = fs.createWriteStream(
`${workspace}/${mkdocsDir}docs/img/${downloadTitle}`,
);
res.body.pipe(writeStream);
// TODO(freben): This cast is sketchy, but for some reason the node types don't quite line up here
// https://stackoverflow.com/questions/44672942/stream-response-to-file-using-fetch-api-and-fs-createwritestream/73879265#73879265
Readable.fromWeb(res.body as any).pipe(writeStream);
await new Promise((resolve, reject) => {
writeStream.on('finish', () => {
resolve(`${workspace}/${mkdocsDir}docs/img/${downloadTitle}`);
@@ -47,7 +47,6 @@
"@backstage/errors": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"node-fetch": "^2.7.0",
"yaml": "^2.0.0"
},
"devDependencies": {
@@ -28,7 +28,6 @@ import {
getRepoSourceDirectory,
parseRepoUrl,
} from '@backstage/plugin-scaffolder-node';
import fetch, { Response, RequestInit } from 'node-fetch';
import { examples } from './gerrit.examples';
const createGerritProject = async (
@@ -47,7 +47,6 @@
"@backstage/errors": "workspace:^",
"@backstage/integration": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"node-fetch": "^2.7.0",
"yaml": "^2.0.0"
},
"devDependencies": {
@@ -30,7 +30,6 @@ import {
} from '@backstage/plugin-scaffolder-node';
import { examples } from './gitea.examples';
import crypto from 'crypto';
import fetch, { Response, RequestInit } from 'node-fetch';
const checkGiteaContentUrl = async (
config: GiteaIntegrationConfig,
@@ -13,17 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
import yaml from 'yaml';
import { createGitlabProjectAccessTokenAction } from './gitlabProjectAccessTokenCreate'; // Adjust the import based on your project structure
import { examples } from './gitlabProjectAccessTokenCreate.examples';
import { DateTime } from 'luxon';
jest.mock('node-fetch');
const mockGitlabClient = {
ProjectAccessTokens: {
create: jest.fn(),
@@ -13,15 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { ConfigReader } from '@backstage/config';
import { ScmIntegrations } from '@backstage/integration';
import { createMockActionContext } from '@backstage/plugin-scaffolder-node-test-utils';
import { createGitlabProjectAccessTokenAction } from './gitlabProjectAccessTokenCreate'; // Adjust the import based on your project structure
import { DateTime } from 'luxon';
jest.mock('node-fetch');
const mockGitlabClient = {
ProjectAccessTokens: {
create: jest.fn(),
@@ -46,7 +46,6 @@
"@backstage/config": "workspace:^",
"@backstage/errors": "workspace:^",
"@backstage/plugin-scaffolder-node": "workspace:^",
"node-fetch": "^2.7.0",
"yaml": "^2.3.3"
},
"devDependencies": {
@@ -17,7 +17,6 @@
import { createTemplateAction } from '@backstage/plugin-scaffolder-node';
import { InputError } from '@backstage/errors';
import { Config } from '@backstage/config';
import fetch from 'node-fetch';
/**
* Creates the `sentry:project:create` Scaffolder action.
@@ -53,8 +53,7 @@
"@backstage/backend-plugin-api": "workspace:^",
"@backstage/config": "workspace:^",
"@backstage/plugin-search-backend-node": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"node-fetch": "^2.7.0"
"@backstage/plugin-search-common": "workspace:^"
},
"devDependencies": {
"@backstage/backend-test-utils": "workspace:^",
@@ -29,7 +29,6 @@ import {
DocumentCollatorFactory,
IndexableDocument,
} from '@backstage/plugin-search-common';
import fetch from 'node-fetch';
import { Readable } from 'stream';
/**
@@ -39,7 +39,6 @@
"@backstage/config": "workspace:^",
"@backstage/plugin-search-backend-node": "workspace:^",
"@backstage/plugin-search-common": "workspace:^",
"node-fetch": "^2.7.0",
"qs": "^6.9.4"
},
"devDependencies": {
@@ -20,7 +20,7 @@ import {
} from '@backstage/plugin-search-common';
import { Config } from '@backstage/config';
import { Readable } from 'stream';
import fetch from 'node-fetch';
import qs from 'qs';
import { LoggerService } from '@backstage/backend-plugin-api';
@@ -60,7 +60,6 @@
"@backstage/plugin-search-common": "workspace:^",
"@backstage/plugin-techdocs-node": "workspace:^",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"p-limit": "^3.1.0"
},
"devDependencies": {
@@ -34,7 +34,6 @@ import { catalogEntityReadPermission } from '@backstage/plugin-catalog-common/al
import { Permission } from '@backstage/plugin-permission-common';
import { DocumentCollatorFactory } from '@backstage/plugin-search-common';
import { TechDocsDocument } from '@backstage/plugin-techdocs-node';
import fetch from 'node-fetch';
import pLimit from 'p-limit';
import { Readable } from 'stream';
import { TechDocsCollatorEntityTransformer } from './TechDocsCollatorEntityTransformer';
-1
View File
@@ -48,7 +48,6 @@
"express": "^4.17.1",
"express-promise-router": "^4.1.0",
"http-proxy-middleware": "^2.0.0",
"node-fetch": "^2.7.0",
"uuid": "^11.0.0",
"winston": "^3.2.1",
"ws": "^8.18.0",
+1 -2
View File
@@ -77,7 +77,6 @@
"fs-extra": "^11.2.0",
"knex": "^3.0.0",
"lodash": "^4.17.21",
"node-fetch": "^2.7.0",
"p-limit": "^3.1.0",
"winston": "^3.2.1"
},
@@ -85,7 +84,7 @@
"@backstage/backend-defaults": "workspace:^",
"@backstage/backend-test-utils": "workspace:^",
"@backstage/cli": "workspace:^",
"msw": "^1.0.0",
"msw": "^2.0.0",
"supertest": "^7.0.0"
},
"configSchema": "config.d.ts"
@@ -22,7 +22,7 @@ import {
registerMswTestHooks,
} from '@backstage/backend-test-utils';
import { setupServer } from 'msw/node';
import { rest } from 'msw';
import { http, HttpResponse } from 'msw';
import { ConfigReader } from '@backstage/config';
import { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';
import { DiscoveryService } from '@backstage/backend-plugin-api';
@@ -106,12 +106,12 @@ describe('TechDocs Collator', () => {
});
worker.use(
rest.get(
http.get(
'http://test-backend/static/docs/default/Component/test-entity-with-docs/search/search_index.json',
(_, res, ctx) => res(ctx.status(200), ctx.json(mockSearchDocIndex)),
() => HttpResponse.json(mockSearchDocIndex),
),
rest.get('http://test-backend/entities', (_, res, ctx) =>
res(ctx.status(200), ctx.json(expectedEntities)),
http.get('http://test-backend/entities', () =>
HttpResponse.json(expectedEntities),
),
);
});
@@ -164,12 +164,12 @@ describe('TechDocs Collator', () => {
});
worker.use(
rest.get(
http.get(
'http://test-backend/static/docs/default/component/test-entity-with-docs/search/search_index.json',
(_, res, ctx) => res(ctx.status(200), ctx.json(mockSearchDocIndex)),
() => HttpResponse.json(mockSearchDocIndex),
),
rest.get('http://test-backend/entities', (_, res, ctx) =>
res(ctx.status(200), ctx.json(expectedEntities)),
http.get('http://test-backend/entities', () =>
HttpResponse.json(expectedEntities),
),
);
});
@@ -21,7 +21,6 @@ import {
RELATION_OWNED_BY,
stringifyEntityRef,
} from '@backstage/catalog-model';
import fetch from 'node-fetch';
import unescape from 'lodash/unescape';
import { Logger } from 'winston';
import pLimit from 'p-limit';
@@ -27,28 +27,23 @@ import * as winston from 'winston';
import { TechDocsCache } from '../cache';
import { DocsBuilder, shouldCheckForUpdate } from '../DocsBuilder';
import { DocsSynchronizer, DocsSynchronizerSyncOpts } from './DocsSynchronizer';
import { mockServices } from '@backstage/backend-test-utils';
import {
mockServices,
registerMswTestHooks,
} from '@backstage/backend-test-utils';
import { DiscoveryService } from '@backstage/backend-plugin-api';
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
jest.mock('../DocsBuilder');
jest.useFakeTimers();
jest.mock('node-fetch', () => ({
__esModule: true,
default: async () => {
return {
json: async () => {
return {
build_timestamp: 123,
};
},
};
},
}));
const MockedDocsBuilder = DocsBuilder as jest.MockedClass<typeof DocsBuilder>;
describe('DocsSynchronizer', () => {
const worker = setupServer();
registerMswTestHooks(worker);
const preparers: jest.Mocked<PreparerBuilder> = {
register: jest.fn(),
get: jest.fn(),
@@ -101,6 +96,13 @@ describe('DocsSynchronizer', () => {
scmIntegrations: ScmIntegrations.fromConfig(new ConfigReader({})),
cache,
});
worker.use(
http.get(
'http://backstage.local/api/techdocs/static/docs/default/component/test/techdocs_metadata.json',
() => HttpResponse.json({ build_timestamp: 123 }),
),
);
});
afterEach(() => {
@@ -27,7 +27,6 @@ import {
PreparerBuilder,
PublisherBase,
} from '@backstage/plugin-techdocs-node';
import fetch from 'node-fetch';
import pLimit, { Limit } from 'p-limit';
import { PassThrough } from 'stream';
import * as winston from 'winston';
+4 -42
View File
@@ -3481,7 +3481,6 @@ __metadata:
minimist: ^1.2.5
morgan: ^1.10.0
msw: ^1.0.0
node-fetch: ^2.7.0
node-forge: ^1.3.1
path-to-regexp: ^8.0.0
selfsigned: ^2.0.0
@@ -4054,7 +4053,6 @@ __metadata:
mini-css-extract-plugin: ^2.4.2
minimatch: ^9.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
node-libs-browser: ^2.2.1
nodemon: ^3.0.1
npm-packlist: ^5.0.0
@@ -4161,7 +4159,6 @@ __metadata:
lodash: ^4.17.21
minimist: ^1.2.5
msw: ^1.0.0
node-fetch: ^2.7.0
typescript-json-schema: ^0.65.0
yaml: ^2.0.0
zen-observable: ^0.10.0
@@ -4590,8 +4587,7 @@ __metadata:
fs-extra: ^11.2.0
handlebars: ^4.7.3
inquirer: ^8.2.0
msw: ^1.0.0
node-fetch: ^2.7.0
msw: ^2.0.0
nodemon: ^3.0.1
ora: ^5.3.0
recursive-readdir: ^2.2.2
@@ -5107,7 +5103,6 @@ __metadata:
knex: ^3.0.0
lodash: ^4.17.21
luxon: ^3.0.0
node-fetch: ^2.7.0
supertest: ^7.0.0
yn: ^4.0.0
languageName: unknown
@@ -5265,7 +5260,6 @@ __metadata:
jose: ^5.0.0
msw: ^2.0.8
node-cache: ^5.1.2
node-fetch: ^2.7.0
languageName: unknown
linkType: soft
@@ -5315,7 +5309,6 @@ __metadata:
"@backstage/plugin-auth-backend": "workspace:^"
"@backstage/plugin-auth-node": "workspace:^"
"@types/passport-oauth2": ^1.4.15
node-fetch: ^2.7.0
passport: ^0.7.0
passport-oauth2: ^1.6.1
supertest: ^7.0.0
@@ -5338,7 +5331,6 @@ __metadata:
express: ^4.18.2
jose: ^5.0.0
msw: ^2.0.0
node-fetch: ^2.7.0
node-mocks-http: ^1.0.0
uuid: ^11.0.0
languageName: unknown
@@ -5438,7 +5430,6 @@ __metadata:
express: ^4.18.2
jose: ^5.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
passport-microsoft: ^1.0.0
supertest: ^7.0.0
languageName: unknown
@@ -5638,7 +5629,6 @@ __metadata:
morgan: ^1.10.0
msw: ^1.0.0
node-cache: ^5.1.2
node-fetch: ^2.7.0
openid-client: ^5.2.1
passport: ^0.7.0
passport-auth0: ^1.4.3
@@ -5701,7 +5691,6 @@ __metadata:
jose: ^5.0.0
lodash: ^4.17.21
msw: ^1.0.0
node-fetch: ^2.7.0
passport: ^0.7.0
supertest: ^7.0.0
uuid: ^11.0.0
@@ -5803,7 +5792,6 @@ __metadata:
"@backstage/plugin-catalog-node": "workspace:^"
luxon: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -5861,10 +5849,8 @@ __metadata:
"@backstage/errors": "workspace:^"
"@backstage/integration": "workspace:^"
"@backstage/plugin-catalog-node": "workspace:^"
"@types/node-fetch": ^2.5.12
luxon: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -5899,7 +5885,6 @@ __metadata:
fs-extra: ^11.2.0
luxon: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -5942,8 +5927,7 @@ __metadata:
lodash: ^4.17.21
luxon: ^3.0.0
minimatch: ^9.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
msw: ^2.0.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -5984,7 +5968,6 @@ __metadata:
lodash: ^4.17.21
luxon: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -6064,11 +6047,9 @@ __metadata:
"@backstage/plugin-catalog-node": "workspace:^"
"@microsoft/microsoft-graph-types": ^2.6.0
"@types/lodash": ^4.14.151
"@types/node-fetch": ^2.5.12
lodash: ^4.17.21
luxon: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
p-limit: ^3.0.2
qs: ^6.9.4
uuid: ^11.0.0
@@ -6113,7 +6094,6 @@ __metadata:
lodash: ^4.17.21
luxon: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -6194,7 +6174,6 @@ __metadata:
luxon: ^3.0.0
minimatch: ^9.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
p-limit: ^3.0.2
prom-client: ^15.0.0
supertest: ^7.0.0
@@ -6585,7 +6564,6 @@ __metadata:
express-promise-router: ^4.1.0
fs-extra: ^11.0.0
lodash: ^4.17.21
node-fetch: ^2.7.0
ping: ^0.4.1
semver: ^7.5.3
supertest: ^7.0.0
@@ -7125,7 +7103,6 @@ __metadata:
express-promise-router: ^4.1.0
knex: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
supertest: ^7.0.0
uuid: ^11.0.0
winston: ^3.2.1
@@ -7157,7 +7134,6 @@ __metadata:
"@backstage/test-utils": "workspace:^"
knex: ^3.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
languageName: unknown
linkType: soft
@@ -7321,7 +7297,6 @@ __metadata:
express-promise-router: ^4.1.0
lodash: ^4.17.21
msw: ^1.0.0
node-fetch: ^2.7.0
supertest: ^7.0.0
yn: ^4.0.0
zod: ^3.22.4
@@ -7416,7 +7391,6 @@ __metadata:
http-proxy-middleware: ^2.0.0
morgan: ^1.10.0
msw: ^2.0.0
node-fetch: ^2.7.0
uuid: ^11.0.0
winston: ^3.2.1
yaml: ^2.0.0
@@ -7456,7 +7430,6 @@ __metadata:
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
fs-extra: ^11.2.0
msw: ^1.0.0
node-fetch: ^2.7.0
yaml: ^2.0.0
languageName: unknown
linkType: soft
@@ -7475,7 +7448,6 @@ __metadata:
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
fs-extra: ^11.2.0
msw: ^1.0.0
node-fetch: ^2.7.0
yaml: ^2.0.0
languageName: unknown
linkType: soft
@@ -7496,7 +7468,6 @@ __metadata:
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
fs-extra: ^11.2.0
msw: ^1.0.0
node-fetch: ^2.7.0
yaml: ^2.0.0
languageName: unknown
linkType: soft
@@ -7517,7 +7488,6 @@ __metadata:
fs-extra: ^11.2.0
git-url-parse: ^15.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
node-html-markdown: ^1.3.0
yaml: ^2.0.0
languageName: unknown
@@ -7577,7 +7547,6 @@ __metadata:
"@backstage/plugin-scaffolder-node": "workspace:^"
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
msw: ^1.0.0
node-fetch: ^2.7.0
yaml: ^2.0.0
languageName: unknown
linkType: soft
@@ -7595,7 +7564,6 @@ __metadata:
"@backstage/plugin-scaffolder-node": "workspace:^"
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
msw: ^1.0.0
node-fetch: ^2.7.0
yaml: ^2.0.0
languageName: unknown
linkType: soft
@@ -7700,7 +7668,6 @@ __metadata:
"@backstage/plugin-scaffolder-node-test-utils": "workspace:^"
"@backstage/types": "workspace:^"
msw: ^2.0.0
node-fetch: ^2.7.0
yaml: ^2.3.3
languageName: unknown
linkType: soft
@@ -8056,7 +8023,6 @@ __metadata:
"@backstage/plugin-search-backend-node": "workspace:^"
"@backstage/plugin-search-common": "workspace:^"
msw: ^1.2.1
node-fetch: ^2.7.0
languageName: unknown
linkType: soft
@@ -8088,7 +8054,6 @@ __metadata:
"@backstage/plugin-search-backend-node": "workspace:^"
"@backstage/plugin-search-common": "workspace:^"
msw: ^1.2.1
node-fetch: ^2.7.0
qs: ^6.9.4
languageName: unknown
linkType: soft
@@ -8112,7 +8077,6 @@ __metadata:
"@backstage/plugin-techdocs-node": "workspace:^"
lodash: ^4.17.21
msw: ^1.0.0
node-fetch: ^2.7.0
p-limit: ^3.1.0
languageName: unknown
linkType: soft
@@ -8287,7 +8251,6 @@ __metadata:
express-promise-router: ^4.1.0
http-proxy-middleware: ^2.0.0
msw: ^1.0.0
node-fetch: ^2.7.0
supertest: ^7.0.0
uuid: ^11.0.0
winston: ^3.2.1
@@ -8436,8 +8399,7 @@ __metadata:
fs-extra: ^11.2.0
knex: ^3.0.0
lodash: ^4.17.21
msw: ^1.0.0
node-fetch: ^2.7.0
msw: ^2.0.0
p-limit: ^3.1.0
supertest: ^7.0.0
winston: ^3.2.1
@@ -19709,7 +19671,7 @@ __metadata:
languageName: node
linkType: hard
"@types/node-fetch@npm:^2.5.12, @types/node-fetch@npm:^2.6.4, @types/node-fetch@npm:^2.6.9":
"@types/node-fetch@npm:^2.6.4, @types/node-fetch@npm:^2.6.9":
version: 2.6.12
resolution: "@types/node-fetch@npm:2.6.12"
dependencies: