generated from actions/typescript-action
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
123 additions
and
61 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,87 +1,58 @@ | ||
import { setFailed } from "@actions/core"; | ||
import fs from "fs"; | ||
import { CustomError } from "ts-custom-error"; | ||
|
||
import { extractArticle } from "./extractors/extractArticle"; | ||
import { extractFeed } from "./extractors/extractFeed"; | ||
import { FeedEntry } from "./extractors/types/feed-extractor"; | ||
import { logger } from "./logger"; | ||
import { UnknownError } from "./utils/errors"; | ||
import { buildFilename, getInputFeedUrls, getOutputDir } from "./utils/utils"; | ||
import { storeFile } from "./utils/fs"; | ||
import { buildFilename, getInputFeedUrls, getOutputDir } from "./utils/io"; | ||
|
||
export async function fetchEntries() { | ||
try { | ||
const outputDir = getOutputDir(); | ||
const feedUrls = getInputFeedUrls(); | ||
|
||
feedUrls.map(async (feedUrl: URL) => { | ||
try { | ||
const feedData = await extractFeed(feedUrl); | ||
if (!feedData) { | ||
logger.warn( | ||
`Feed %s does not contain any entry. Cannot continue.`, | ||
feedUrl, | ||
); | ||
return; | ||
} | ||
|
||
// Check if directory exists; if not, create it | ||
if (!fs.existsSync(outputDir)) { | ||
fs.mkdirSync(outputDir, { recursive: true }); | ||
} | ||
|
||
void Promise.all( | ||
feedData.entries.map(async (feedEntry) => { | ||
try { | ||
const article = await extractArticle(feedEntry); | ||
|
||
if (!article) { | ||
logger.warn( | ||
`Article "%s" is not valid or does not contain a defined url. Cannot store it.`, | ||
feedEntry.link, | ||
); | ||
return; | ||
} | ||
|
||
const filename = buildFilename(article.url); | ||
const destinationFile = `${outputDir}/${filename}.json`; | ||
if (fs.existsSync(destinationFile)) { | ||
logger.debug( | ||
`Article "%s" already exists on path "%s"`, | ||
article.url, | ||
destinationFile, | ||
); | ||
return; | ||
} | ||
|
||
const fileContent = JSON.stringify(article, null, 2); | ||
fs.writeFileSync(destinationFile, fileContent, { | ||
encoding: "utf8", | ||
}); | ||
logger.info( | ||
`New article stored: "%s". Path: "%s"`, | ||
article.url, | ||
destinationFile, | ||
); | ||
} catch (err) { | ||
if (err instanceof CustomError) { | ||
logger.warn(err.message); | ||
return; | ||
} | ||
setFailed(new UnknownError(err).message); | ||
return; | ||
} | ||
}), | ||
); | ||
void Promise.all(feedData.entries.map(processEntry)); | ||
} catch (err) { | ||
if (err instanceof CustomError) { | ||
logger.warn(err.message); | ||
return; | ||
} | ||
|
||
setFailed(new UnknownError(err).message); | ||
return; | ||
} | ||
}); | ||
} catch (error) { | ||
setFailed(new UnknownError(error).message); | ||
return; | ||
} | ||
} | ||
|
||
async function processEntry(feedEntry: FeedEntry) { | ||
const outputDir = getOutputDir(); | ||
try { | ||
const article = await extractArticle(feedEntry); | ||
const filename = buildFilename(article.url); | ||
const destinationFile = `${outputDir}/${filename}.json`; | ||
const fileContents = JSON.stringify(article, null, 2); | ||
storeFile(destinationFile, fileContents); | ||
logger.info( | ||
`New article stored: "%s". Path: "%s"`, | ||
article.url, | ||
destinationFile, | ||
); | ||
} catch (err) { | ||
if (err instanceof CustomError) { | ||
logger.warn(err.message); | ||
return; | ||
} | ||
|
||
setFailed(new UnknownError(err).message); | ||
return; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import fs from "fs"; | ||
|
||
import { FileExistsError, storeFile } from "./fs"; | ||
|
||
jest.mock("fs"); | ||
|
||
describe("fs", () => { | ||
describe("storeFile", () => { | ||
it("throws FileExistsError if file already exists", () => { | ||
fs.existsSync = jest.fn().mockReturnValue(true); | ||
expect(() => storeFile("some-file.json", "fileContents")).toThrow( | ||
FileExistsError, | ||
); | ||
}); | ||
|
||
it("creates the file", () => { | ||
const expectedPath = `dir/file.json`; | ||
const expectedContent = "fileContents"; | ||
fs.existsSync = jest.fn(); | ||
fs.mkdirSync = jest.fn(); | ||
fs.writeFileSync = jest.fn(); | ||
|
||
storeFile(expectedPath, expectedContent); | ||
expect(fs.writeFileSync).toHaveBeenCalledWith( | ||
expectedPath, | ||
expectedContent, | ||
{ encoding: "utf8" }, | ||
); | ||
}); | ||
|
||
it("creates the dir if it does not exists", () => { | ||
const expectedDir = "dir"; | ||
const path = `${expectedDir}/file.json`; | ||
fs.existsSync = jest | ||
.fn() | ||
// File exists | ||
.mockReturnValueOnce(false) | ||
// Dir exists | ||
.mockReturnValueOnce(false); | ||
|
||
fs.mkdirSync = jest.fn(); | ||
|
||
storeFile(path, "fileContents"); | ||
expect(fs.mkdirSync).toHaveBeenCalledWith(expectedDir, { | ||
recursive: true, | ||
}); | ||
}); | ||
|
||
it("does not created the dir if it exists already", () => { | ||
const expectedDir = "dir"; | ||
const path = `${expectedDir}/file.json`; | ||
fs.existsSync = jest | ||
.fn() | ||
// File exists | ||
.mockReturnValueOnce(false) | ||
// Dir exists | ||
.mockReturnValueOnce(true); | ||
|
||
fs.mkdirSync = jest.fn(); | ||
|
||
storeFile(path, "fileContents"); | ||
expect(fs.mkdirSync).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import fs from "fs"; | ||
import path from "path"; | ||
import { CustomError } from "ts-custom-error"; | ||
|
||
export function storeFile(destinationPath: string, fileContents: string) { | ||
if (fs.existsSync(destinationPath)) { | ||
throw new FileExistsError(destinationPath); | ||
} | ||
|
||
const dir = path.dirname(destinationPath); | ||
if (!fs.existsSync(dir)) { | ||
fs.mkdirSync(dir, { recursive: true }); | ||
} | ||
|
||
fs.writeFileSync(destinationPath, fileContents, { | ||
encoding: "utf8", | ||
}); | ||
} | ||
|
||
export class FileExistsError extends CustomError { | ||
public constructor(path: string) { | ||
super(`The file "${path}" already exists`); | ||
// Set name explicitly as minification can mangle class names | ||
Object.defineProperty(this, "name", { value: "FileExistsError" }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
File renamed without changes.