mirror of
https://github.com/wassname/talk.git
synced 2026-09-11 12:51:33 +08:00
[next] Tasks (#1777)
* feat: initial support for synced tenants * fix: cleanup * fix: logger now respects logging level * fix: cache now ignores updates issued from itself * feat: print subscriber count * feat: initial moderation + validation for new comments * fix: added Promiseable type * feat: initial actions impl * feat: more moderation phases * fix: handle settings inheritence * fix: moved settings into new file * fix: defaults and documentation * fix: replace merge with object spread * feat: added integration with akismet * fix: support tenant cache for oidc strategy * fix: fixed compile * fix: import ordering * feat: added bull for queue support * feat: support for scraping * fix: fixes for scraper - Implemented simple metascraper replacement (to resolve security advisory warning) - Implemented simle dotize replacement (to resolve not working version that couldn't handle date objects) - Plugged in asset scraping to asset creation process * fix: handles array values * feat: added initial scraper implementation * feat: seperate queues but share config * fix: simplified auth data access * feat: moved more settings into the graph * feat: improved mailer design * fix: fixed issue with dotize * fix: fixed some issues with adapter * fix: queue cleanup * feat: added organizationName to Tenant * feat: email rendering * review: support es6 imports * fix: restore old ci step * fix: adjusted logging messages
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { dotize } from "talk-common/utils/dotize";
|
||||
|
||||
it("converts nested properties", () => {
|
||||
const input = {
|
||||
a: "property",
|
||||
can: { be: "nested", really: { deeply: "sometimes" } },
|
||||
};
|
||||
const output = dotize(input);
|
||||
|
||||
expect(output).toEqual({
|
||||
a: "property",
|
||||
"can.be": "nested",
|
||||
"can.really.deeply": "sometimes",
|
||||
});
|
||||
});
|
||||
|
||||
it("converts properties with dates", () => {
|
||||
const now = new Date();
|
||||
const input = { a: now, can: { be: now } };
|
||||
const output = dotize(input);
|
||||
|
||||
expect(output).toEqual({
|
||||
a: now,
|
||||
"can.be": now,
|
||||
});
|
||||
});
|
||||
|
||||
it("converts array properties when enabled", () => {
|
||||
const input = {
|
||||
a: [
|
||||
{ property: "with", an: "array" },
|
||||
{ value: [{ sometimes: "nested" }] },
|
||||
],
|
||||
other: { times: "not" },
|
||||
};
|
||||
const output = dotize(input);
|
||||
|
||||
expect(output).toEqual({
|
||||
"a[0].property": "with",
|
||||
"a[0].an": "array",
|
||||
"a[1].value[0].sometimes": "nested",
|
||||
"other.times": "not",
|
||||
});
|
||||
});
|
||||
|
||||
it("does not converts array properties when disabled", () => {
|
||||
const input = {
|
||||
a: [
|
||||
{ property: "with", an: "array" },
|
||||
{ value: [{ sometimes: "nested" }] },
|
||||
],
|
||||
other: { times: "not" },
|
||||
};
|
||||
const output = dotize(input, { ignoreArrays: true });
|
||||
|
||||
expect(output).toEqual({
|
||||
"other.times": "not",
|
||||
});
|
||||
});
|
||||
|
||||
it("does convert array properties properly", () => {
|
||||
expect(
|
||||
dotize({ wordlist: { banned: ["banned"] } }, { embedArrays: true })
|
||||
).toEqual({
|
||||
"wordlist.banned": ["banned"],
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,82 @@
|
||||
import { isArray, isNull, isNumber, isPlainObject, isString } from "lodash";
|
||||
|
||||
function isObject(obj: any): obj is Record<string, any> {
|
||||
return isPlainObject(obj);
|
||||
}
|
||||
|
||||
function deriveKey(property: string, prefix?: string) {
|
||||
if (prefix) {
|
||||
return `${prefix}.${property}`;
|
||||
}
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
function reduce(
|
||||
result: Record<string, any>,
|
||||
obj: Record<string, any> | number | null | string,
|
||||
ignoreArrays: boolean,
|
||||
embedArrays: boolean,
|
||||
prefix?: string
|
||||
) {
|
||||
if (prefix) {
|
||||
if (isNumber(obj) || isString(obj) || isNull(obj)) {
|
||||
result[prefix] = obj;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (isObject(obj)) {
|
||||
for (const property in obj) {
|
||||
if (!obj.hasOwnProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const value = obj[property];
|
||||
const key = deriveKey(property, prefix);
|
||||
|
||||
if (isPlainObject(value)) {
|
||||
reduce(result, value, ignoreArrays, embedArrays, key);
|
||||
} else if (isArray(value)) {
|
||||
if (!ignoreArrays) {
|
||||
if (embedArrays) {
|
||||
result[key] = value;
|
||||
} else {
|
||||
value.forEach((item, index) => {
|
||||
reduce(
|
||||
result,
|
||||
item,
|
||||
ignoreArrays,
|
||||
embedArrays,
|
||||
`${key}[${index}]`
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export interface DotizeOptions {
|
||||
/**
|
||||
* ignoreArrays will ignore all array properties and not include them in the
|
||||
* resulting entry.
|
||||
*/
|
||||
ignoreArrays?: boolean;
|
||||
|
||||
/**
|
||||
* embedArrays will treat arrays as plain objects, and embed them as is
|
||||
* without recusing the dotize algorithm to it.
|
||||
*/
|
||||
embedArrays?: boolean;
|
||||
}
|
||||
|
||||
export const dotize = (
|
||||
obj: Record<string, any>,
|
||||
{ ignoreArrays = false, embedArrays = false }: DotizeOptions = {}
|
||||
): Record<string, any> => reduce({}, obj, ignoreArrays, embedArrays);
|
||||
Reference in New Issue
Block a user