mirror of
https://github.com/strapi/strapi.git
synced 2025-08-10 01:38:10 +00:00
112 lines
2.2 KiB
TypeScript
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);
|