2022-11-28 16:41:51 +01:00

112 lines
2.2 KiB
TypeScript

import type { Readable } from 'stream';
import { isArray, isObject, zip, isEqual, uniq, mapValues, pick } from 'lodash/fp';
import type { Context, Diff } from '../types';
/**
* Collect every entity in a Readable stream
*/
export const collect = <T = unknown>(stream: Readable): Promise<T[]> => {
const chunks: T[] = [];
return new Promise((resolve) => {
stream.on('data', (chunk) => chunks.push(chunk));
stream.on('end', () => {
stream.destroy();
resolve(chunks);
});
});
};
const createContext = (): Context => ({ path: [] });
export const jsonDiffs = (a: unknown, b: unknown, ctx: Context = createContext()): Diff[] => {
const diffs: Diff[] = [];
const { path } = ctx;
const aType = typeof a;
const bType = typeof b;
// Define helpers
const added = () => {
diffs.push({ kind: 'added', path, type: bType, value: b });
return diffs;
};
const deleted = () => {
diffs.push({ kind: 'deleted', path, type: aType, value: a });
return diffs;
};
const modified = () => {
diffs.push({
kind: 'modified',
path,
types: [aType, bType],
values: [a, b],
});
return diffs;
};
if (aType === 'undefined') {
return added();
}
if (bType === 'undefined') {
return deleted();
}
if (isArray(a) && isArray(b)) {
let k = 0;
for (const [aItem, bItem] of zip(a, b)) {
const kCtx: Context = { path: [...path, k.toString()] };
const kDiffs = jsonDiffs(aItem, bItem, kCtx);
diffs.push(...kDiffs);
k += 1;
}
return diffs;
}
if (isObject(a) && isObject(b)) {
const keys = uniq(Object.keys(a).concat(Object.keys(b)));
for (const key of keys) {
const aValue = (a as any)[key];
const bValue = (b as any)[key];
const nestedDiffs = jsonDiffs(aValue, bValue, { path: [...path, key] });
diffs.push(...nestedDiffs);
}
return diffs;
}
if (!isEqual(a, b)) {
modified();
}
return diffs;
};
const schemaSelectedKeys = [
'collectionName',
'info',
'options',
'pluginOptions',
'attributes',
'kind',
'modelType',
'modelName',
'uid',
'plugin',
'globalId',
];
export const mapSchemasValues = (schemas: any) => mapValues(pick(schemaSelectedKeys), schemas);