-
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.
* feat: Add first mapper UserMapper with getDto() * feat: Rewrote fieldmapper to give more info per field * feat: Add FeedMapper * feat: Added SourceMapper * feat: Add sourcemapper .. .. set default cli output to json * feat: Add PlatformMapper and mappings for all platforms * Dont stringify json in dto * feat: Add PostMapper * chore: Minor fixes * feat: Standardized the output in Fairpost.ts * feat: Handle CombinedResult prettier * chore: Remove unused methods * feat: Properly type things and let Fairpost throw errors if needed * feat: Add files to sourcemapper --------- Co-authored-by: pike <[email protected]>
- Loading branch information
1 parent
bed51fa
commit ec3b371
Showing
25 changed files
with
1,440 additions
and
350 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
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
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,120 @@ | ||
import User from "../models/User"; | ||
import Operator from "../models/Operator"; | ||
import { FileInfo } from "../models/Source"; | ||
import { PostStatus, PostResult } from "../models/Post"; | ||
|
||
export interface FieldMapping { | ||
[field: string]: { | ||
type: | ||
| "string" | ||
| "string[]" | ||
| "integer" | ||
| "float" | ||
| "boolean" | ||
| "date" | ||
| "json"; | ||
label: string; | ||
get: string[]; // (permissions | any | none)[] | ||
set: string[]; // (permissions | any | none)[] | ||
required?: boolean; // only if settable | ||
default?: string | string[] | number | boolean | Date | object; | ||
}; | ||
} | ||
export type Dto<T extends Record<string, unknown> = Record<string, unknown>> = { | ||
[K in keyof T]: | ||
| string | ||
| string[] | ||
| number | ||
| boolean | ||
| FileInfo[] | ||
| PostResult[] | ||
| PostStatus | ||
| undefined; | ||
}; | ||
|
||
/** | ||
* AbstractMapper - base for all mappers | ||
* | ||
* The mappers are used to create mapped versions of the models; | ||
* for example, to send to or read from a client or a database. | ||
* | ||
* All mappers require a *user* because the user can optionally | ||
* configure what data is visible, fe to the operator. | ||
* | ||
* For get operations, the mapper shall only return the fields | ||
* allowed to be get by the operator. | ||
* | ||
* For set operations, the mapper shall return | ||
* only the fields allowed to be set by the operator. | ||
* | ||
*/ | ||
|
||
export default abstract class AbstractMapper<ModelDto extends Dto> { | ||
protected user: User; | ||
|
||
constructor(user: User) { | ||
this.user = user; | ||
} | ||
|
||
protected abstract mapping: FieldMapping; | ||
|
||
public getReport(operator: Operator): string { | ||
const dto = this.getDto(operator); | ||
const lines: string[] = []; | ||
for (const field in dto) { | ||
let line = ""; | ||
if (field in this.mapping) { | ||
line += this.mapping[field].label + ": "; | ||
} else { | ||
line += field + ": "; | ||
} | ||
if (dto[field] instanceof Array) { | ||
lines.push(line); | ||
(dto[field] as string[]).forEach((item) => { | ||
lines.push(" - " + String(item)); | ||
}); | ||
} else { | ||
line += String(dto[field]); | ||
lines.push(line); | ||
} | ||
} | ||
return lines.join("\n"); | ||
} | ||
|
||
/** | ||
* Return a dto based on the operator | ||
* @param operator | ||
* @returns key/value pairs for the dto | ||
*/ | ||
abstract getDto(operator: Operator): ModelDto; | ||
|
||
/** | ||
* Insert a given dto based on the operator | ||
* @param operator | ||
* @param dto | ||
* @returns boolean success | ||
*/ | ||
abstract setDto(operator: Operator, dto: ModelDto): boolean; | ||
|
||
protected getDtoFields( | ||
operator: Operator, | ||
operation: "get" | "set", | ||
): string[] { | ||
const permissions = operator.getPermissions(this.user); | ||
const fields = Object.keys(this.mapping).filter((field) => { | ||
if (this.mapping[field][operation].includes("none")) return false; | ||
if (this.mapping[field][operation].includes("any")) return true; | ||
if ( | ||
this.mapping[field][operation].some( | ||
(permission) => | ||
permission in permissions && | ||
permissions[permission as keyof typeof permissions], | ||
) | ||
) { | ||
return true; | ||
} | ||
return false; | ||
}); | ||
return fields; | ||
} | ||
} |
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,140 @@ | ||
import AbstractMapper from "./AbstractMapper"; | ||
import { Dto, FieldMapping } from "./AbstractMapper"; | ||
import Operator from "../models/Operator"; | ||
import Feed from "../models/Feed"; | ||
|
||
export interface FeedDto | ||
extends Dto<{ | ||
model?: string; | ||
id?: string; | ||
user_id?: string; | ||
path?: string; | ||
platforms?: string[]; | ||
sources?: string[]; | ||
interval?: number; | ||
}> {} | ||
|
||
export default class FeedMapper extends AbstractMapper<FeedDto> { | ||
private feed: Feed; | ||
mapping: FieldMapping = { | ||
model: { | ||
type: "string", | ||
label: "Model", | ||
get: ["any"], | ||
set: ["none"], | ||
}, | ||
id: { | ||
type: "string", | ||
label: "ID", | ||
get: ["any"], | ||
set: ["none"], | ||
}, | ||
user_id: { | ||
type: "string", | ||
label: "User ID", | ||
get: ["any"], | ||
set: ["none"], | ||
}, | ||
path: { | ||
type: "string", | ||
label: "Path", | ||
get: ["manageFeed"], | ||
set: ["none"], | ||
}, | ||
platforms: { | ||
type: "string[]", | ||
label: "Enabled platforms", | ||
get: ["manageFeed"], | ||
set: ["manageFeed"], | ||
required: false, | ||
}, | ||
sources: { | ||
type: "string[]", | ||
label: "Feed sources", | ||
get: ["manageFeed"], | ||
set: ["none"], | ||
required: false, | ||
}, | ||
interval: { | ||
type: "float", | ||
label: "Post interval", | ||
get: ["manageFeed"], | ||
set: ["manageFeed"], | ||
required: false, | ||
}, | ||
}; | ||
|
||
constructor(feed: Feed) { | ||
super(feed.user); | ||
this.feed = feed; | ||
} | ||
|
||
/** | ||
* Return a dto based on the operator and operation | ||
* @param operator | ||
* @returns key/value pairs for the dto | ||
*/ | ||
getDto(operator: Operator): FeedDto { | ||
const fields = this.getDtoFields(operator, "get"); | ||
const dto: FeedDto = {}; | ||
fields.forEach((field) => { | ||
switch (field) { | ||
case "model": | ||
dto[field] = "feed"; | ||
break; | ||
case "id": | ||
dto[field] = this.feed.id; | ||
break; | ||
case "user_id": | ||
dto[field] = this.user.id; | ||
break; | ||
case "path": | ||
dto[field] = this.feed.path; | ||
break; | ||
case "platforms": | ||
dto[field] = Object.keys(this.feed.platforms); | ||
break; | ||
case "sources": | ||
dto[field] = this.feed.getSources().map((s) => s.id); | ||
break; | ||
case "interval": | ||
dto[field] = this.feed.interval; | ||
break; | ||
} | ||
}); | ||
return dto; | ||
} | ||
|
||
/** | ||
* Insert a given dto based on the operator | ||
* @param operator | ||
* @param dto | ||
* @returns boolean success | ||
*/ | ||
setDto(operator: Operator, dto: FeedDto): boolean { | ||
const fields = this.getDtoFields(operator, "set"); | ||
for (const field in dto) { | ||
if (field in fields) { | ||
switch (field) { | ||
case "platforms": | ||
this.user.set( | ||
"settings", | ||
"FEED_PLATFORMS", | ||
(dto[field] as string[]).join(","), | ||
); | ||
break; | ||
case "interval": | ||
this.user.set( | ||
"settings", | ||
"FEED_INTERVAL", | ||
String(dto[field] || 24), | ||
); | ||
break; | ||
} | ||
} else { | ||
throw this.user.error("Unknown field: " + field); | ||
} | ||
} | ||
return true; | ||
} | ||
} |
Oops, something went wrong.