Skip to content

Commit

Permalink
Merge branch 'feature/50-pre-scanner' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Zhykos committed Oct 31, 2024
2 parents 7e4c4ef + 0eace66 commit b829af4
Show file tree
Hide file tree
Showing 28 changed files with 372 additions and 162 deletions.
7 changes: 1 addition & 6 deletions .github/workflows/deno.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,8 @@ jobs:
with:
deno-version: v2.x

- name: Install biome linting tool
run: |
deno add npm:@biomejs/biome@1.9.4
deno install --allow-scripts=npm:@biomejs/biome@1.9.4
- name: Run linter
run: deno task lint
run: deno lint

- name: Run tests and activate coverage
run: deno test --allow-read --allow-write --unstable-kv --allow-env --allow-net --coverage -- config.yml --database=./test/it-database.sqlite3 --scan
Expand Down
3 changes: 2 additions & 1 deletion deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"nodeModulesDir": "auto",
"tasks": {
"test": "deno test --allow-read --allow-write --trace-leaks --unstable-kv --allow-env --allow-net -- config.yml --database=./test/it-database.sqlite3 --scan",
"coverage": "rm -fr coverage && deno test --allow-read --allow-write --unstable-kv --allow-env --allow-net --coverage -- config.yml --database=./test/it-database.sqlite3 --scan && deno coverage --html --exclude=\"/test/\" && open coverage/html/index.html",
"coverage": "rm -fr coverage && deno test --allow-read --allow-write --unstable-kv --allow-env --allow-net --coverage --fail-fast -- config.yml --database=./test/it-database.sqlite3 --scan && deno coverage --html --exclude=\"/test/\" && open coverage/html/index.html",
"lcov": "deno coverage --lcov --output=cov.lcov --exclude=\"/test/\"",
"lint": "deno lint && deno run -A npm:@biomejs/biome lint",
"format": "deno run -A npm:@biomejs/biome check --write",
Expand All @@ -14,6 +14,7 @@
"imports": {
"@atproto/api": "npm:@atproto/api@^0.13.11",
"@biomejs/biome": "npm:@biomejs/biome@1.9.4",
"@cross/log": "jsr:@cross/log@^0.10.5",
"@std/assert": "jsr:@std/assert@^1.0.5",
"@std/cli": "jsr:@std/cli@^1.0.6",
"@std/collections": "jsr:@std/collections@^1.0.7",
Expand Down
34 changes: 34 additions & 0 deletions deno.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 15 additions & 14 deletions src/cli/domain/aggregate/CLI.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,27 @@
import type { File } from "../../../common/domain/valueobject/File.ts";
import type { Action } from "../valueobject/Action.ts";
import { BlueskyCredentials } from "../valueobject/BlueskyCredentials.ts";
import { BlueskyPublisherAction } from "../valueobject/BlueskyPublisherAction.ts";
import { PreScannerAction } from "../valueobject/PreScannerAction.ts";
import { ScannerAction } from "../valueobject/ScannerAction.ts";

export class CLI {
constructor(
public readonly configuration: File,
public readonly action: Action,
public readonly databaseFilepath = "./db.autophoto.sqlite3",
public readonly debugDatabase = false,
public readonly debug = false,
) {}

static builder() {
return new CLIBuilder();
}
}

class ScannerAction implements Action {
isScan(): boolean {
return true;
}
}

export class CLIBuilder {
private configuration: File | undefined;
private action: Action | undefined;
private databaseFilepath: string | undefined;
private debugDatabase = false;
private debug = false;

withConfiguration(configuration: File) {
this.configuration = configuration;
Expand All @@ -43,12 +39,17 @@ export class CLIBuilder {
}

withBluesky(host: URL, login: string, password: string) {
this.action = new BlueskyCredentials(host, login, password);
this.action = new BlueskyPublisherAction(host, login, password);
return this;
}

withDebug() {
this.debug = true;
return this;
}

withDebugDatabase() {
this.debugDatabase = true;
withPreScanner(configuration: File) {
this.action = new PreScannerAction(configuration);
return this;
}

Expand All @@ -58,14 +59,14 @@ export class CLIBuilder {
}

if (!this.action) {
throw new Error("Action is required: scanner or bluesky publisher");
throw new Error("Action is required: prescanner, publisher or scanner");
}

return new CLI(
this.configuration,
this.action,
this.databaseFilepath,
this.debugDatabase,
this.debug,
);
}
}
8 changes: 7 additions & 1 deletion src/cli/domain/valueobject/Action.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export interface Action {
isScan(): boolean;
type(): ActionType;
}

export enum ActionType {
PRESCANNER = "PRESCANNER",
PUBLISHER = "PUBLISHER",
SCANNER = "SCANNER",
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { DomainError } from "../../../common/domain/DomainError.ts";
import type { ValueObject } from "../../../common/domain/ValueObject.ts";
import type { Action } from "./Action.ts";
import { type Action, ActionType } from "./Action.ts";

export class BlueskyCredentials implements ValueObject, Action {
export class BlueskyPublisherAction implements ValueObject, Action {
constructor(
public readonly host: URL,
public readonly login: string,
Expand All @@ -22,7 +22,7 @@ export class BlueskyCredentials implements ValueObject, Action {
}

equals(other: unknown): boolean {
if (other instanceof BlueskyCredentials) {
if (other instanceof BlueskyPublisherAction) {
return (
this.login === other.login &&
this.password === other.password &&
Expand All @@ -32,7 +32,7 @@ export class BlueskyCredentials implements ValueObject, Action {
return false;
}

isScan(): boolean {
return false;
type(): ActionType {
return ActionType.PUBLISHER;
}
}
10 changes: 10 additions & 0 deletions src/cli/domain/valueobject/PreScannerAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { File } from "../../../common/domain/valueobject/File.ts";
import { type Action, ActionType } from "./Action.ts";

export class PreScannerAction implements Action {
constructor(public readonly configuration: File) {}

type(): ActionType {
return ActionType.PRESCANNER;
}
}
7 changes: 7 additions & 0 deletions src/cli/domain/valueobject/ScannerAction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { type Action, ActionType } from "./Action.ts";

export class ScannerAction implements Action {
type(): ActionType {
return ActionType.SCANNER;
}
}
18 changes: 13 additions & 5 deletions src/cli/service/CLIService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,14 @@ import { CLI, type CLIBuilder } from "../domain/aggregate/CLI.ts";
export class CLIService {
read(cliArgs: string[]): CLI {
const args: Args = parseArgs(cliArgs, {
boolean: ["debug-database", "publish", "scan"],
string: ["bluesky_host", "bluesky_login", "bluesky_passord", "database"],
boolean: ["debug", "publish", "scan"],
string: [
"bluesky_host",
"bluesky_login",
"bluesky_passord",
"database",
"prescan",
],
});

const cliParameters: (string | number)[] = args._;
Expand Down Expand Up @@ -41,8 +47,8 @@ export class CLIService {
.withConfiguration(new File(new Path(filepath)))
.withDatabaseFilepath(databaseFilepath);

if (args["debug-database"] === true) {
cliBuilder.withDebugDatabase();
if (args.debug === true) {
cliBuilder.withDebug();
}

if (args.publish === true) {
Expand All @@ -55,8 +61,10 @@ export class CLIService {
);
} else if (args.scan === true) {
cliBuilder.withScanner();
} else if (args.prescan) {
cliBuilder.withPreScanner(new File(new Path(args.prescan)));
} else {
throw new Error('Missing option: "--scan" or "--publish"');
throw new Error('Missing option: "--prescan" or "--publish" or "--scan"');
}

return cliBuilder.build();
Expand Down
39 changes: 4 additions & 35 deletions src/common/domain/valueobject/Directory.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { DomainError } from "../../../common/domain/DomainError.ts";
import type { ValueObject } from "../../../common/domain/ValueObject.ts";
import { isDirectory } from "../../../utils/file.ts";
import { scanDirectory } from "../../../utils/scan-directory.ts";
import { File } from "./File.ts";
import { Path } from "./Path.ts";

Expand All @@ -22,43 +23,11 @@ export class Directory implements ValueObject {
return false;
}

public async scanDirectories(pattern: RegExp): Promise<File[]> {
public scanDirectories(pattern: RegExp): File[] {
const files: File[] = [];
await Directory.scanDirectory(this.path.value, pattern, (file: File) =>
files.push(file),
scanDirectory(this.path.value, pattern, (file: string) =>
files.push(new File(new Path(file))),
);
return files;
}

private static async scanDirectory(
directory: string,
pattern: RegExp,
onFileAdded: (file: File) => void,
): Promise<void> {
for await (const dirEntry of Deno.readDir(directory)) {
if (dirEntry.isDirectory) {
if (dirEntry.name === "@eaDir") {
continue;
}

await Directory.scanDirectory(
`${directory}/${dirEntry.name}`,
pattern,
onFileAdded,
);
} else if (dirEntry.isFile) {
if (dirEntry.name === ".DS_Store") {
continue;
}

const fullPath = `${directory}/${dirEntry.name}`;
if (!pattern.test(fullPath)) {
continue;
}

const file = new File(new Path(fullPath));
onFileAdded(file);
}
}
}
}
3 changes: 3 additions & 0 deletions src/main-cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { main } from "./main";

Deno.exit((await main(Deno.args)) ? 0 : 1);
38 changes: 25 additions & 13 deletions src/main.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,49 @@
import { Log } from "@cross/log";
import type { CLI } from "./cli/domain/aggregate/CLI.ts";
import type { BlueskyCredentials } from "./cli/domain/valueobject/BlueskyCredentials.ts";
import { ActionType } from "./cli/domain/valueobject/Action.ts";
import type { BlueskyPublisherAction } from "./cli/domain/valueobject/BlueskyPublisherAction.ts";
import type { PreScannerAction } from "./cli/domain/valueobject/PreScannerAction.ts";
import { CLIService } from "./cli/service/CLIService.ts";
import { KvDriver } from "./common/dbdriver/KvDriver.ts";
import type { Configuration } from "./configuration/domain/aggregate/Configuration.ts";
import { ConfigurationService } from "./configuration/service/ConfigurationService.ts";
import { preScan } from "./prescan.ts";
import { publish } from "./publish.ts";
import { runScanner } from "./scan.ts";

await main(Deno.args);

export async function main(cliArgs: string[]): Promise<void> {
export async function main(cliArgs: string[]): Promise<boolean> {
console.log("Starting Autophoto...");

const cli: CLI = new CLIService().read(cliArgs);
const kvDriver = new KvDriver(cli.databaseFilepath);
const logger = new Log();

try {
const configuration: Configuration = new ConfigurationService().loadFile(
cli.configuration.path.value,
);

if (cli.action.isScan()) {
if (cli.action.type() === ActionType.SCANNER) {
console.log("Scanning...");
await runScanner(configuration, kvDriver, cli.debugDatabase);
} else {
const configuration: Configuration = new ConfigurationService().loadFile(
cli.configuration.path.value,
);
await runScanner(configuration, kvDriver, cli.debug);
return true;
}

if (cli.action.type() === ActionType.PUBLISHER) {
console.log("Publishing...");
const result: string | undefined = await publish(
cli.action as BlueskyCredentials,
cli.action as BlueskyPublisherAction,
kvDriver,
cli.debugDatabase,
cli.debug,
);
console.log("Publication result:", result ?? "Nothing to publish.");
return true;
}

console.log("Pre-scanning...");
const configuration: Configuration = new ConfigurationService().loadFile(
(cli.action as PreScannerAction).configuration.path.value,
);
return preScan(configuration, logger);
} finally {
kvDriver.close();
console.log("Autophoto finished.");
Expand Down
Loading

0 comments on commit b829af4

Please sign in to comment.