@strapi/utils
Version:
Shared utilities for the Strapi packages
157 lines (154 loc) • 4.84 kB
JavaScript
import { isNil, pick } from 'lodash/fp';
const DEFAULT_PATH = {
raw: null,
attribute: null
};
var traverseFactory = (()=>{
const state = {
parsers: [],
interceptors: [],
ignore: [],
handlers: {
attributes: [],
common: []
}
};
const traverse = async (visitor, options, data)=>{
const { path = DEFAULT_PATH, parent, schema, getModel } = options ?? {};
// interceptors
for (const { predicate, handler } of state.interceptors){
if (predicate(data)) {
return handler(visitor, options, data, {
recurse: traverse
});
}
}
// parsers
const parser = state.parsers.find((parser)=>parser.predicate(data))?.parser;
const utils = parser?.(data);
// Return the data untouched if we don't know how to traverse it
if (!utils) {
return data;
}
// main loop
let out = utils.transform(data);
const keys = utils.keys(out);
for (const key of keys){
const attribute = schema?.attributes?.[key];
const newPath = {
...path
};
newPath.raw = isNil(path.raw) ? key : `${path.raw}.${key}`;
if (!isNil(attribute)) {
newPath.attribute = isNil(path.attribute) ? key : `${path.attribute}.${key}`;
}
// visitors
const visitorOptions = {
key,
value: utils.get(key, out),
attribute,
schema,
path: newPath,
data: out,
getModel,
parent
};
const transformUtils = {
remove (key) {
out = utils.remove(key, out);
},
set (key, value) {
out = utils.set(key, value, out);
},
recurse: traverse
};
await visitor(visitorOptions, pick([
'remove',
'set'
], transformUtils));
const value = utils.get(key, out);
const createContext = ()=>({
key,
value,
attribute,
schema,
path: newPath,
data: out,
visitor,
getModel,
parent
});
// ignore
const ignoreCtx = createContext();
const shouldIgnore = state.ignore.some((predicate)=>predicate(ignoreCtx));
if (shouldIgnore) {
continue;
}
// handlers
const handlers = [
...state.handlers.common,
...state.handlers.attributes
];
for await (const handler of handlers){
const ctx = createContext();
const pass = await handler.predicate(ctx);
if (pass) {
await handler.handler(ctx, pick([
'recurse',
'set'
], transformUtils));
}
}
}
return out;
};
return {
traverse,
intercept (predicate, handler) {
state.interceptors.push({
predicate,
handler
});
return this;
},
parse (predicate, parser) {
state.parsers.push({
predicate,
parser
});
return this;
},
ignore (predicate) {
state.ignore.push(predicate);
return this;
},
on (predicate, handler) {
state.handlers.common.push({
predicate,
handler
});
return this;
},
onAttribute (predicate, handler) {
state.handlers.attributes.push({
predicate,
handler
});
return this;
},
onRelation (handler) {
return this.onAttribute(({ attribute })=>attribute?.type === 'relation', handler);
},
onMedia (handler) {
return this.onAttribute(({ attribute })=>attribute?.type === 'media', handler);
},
onComponent (handler) {
return this.onAttribute(({ attribute })=>attribute?.type === 'component', handler);
},
onDynamicZone (handler) {
return this.onAttribute(({ attribute })=>attribute?.type === 'dynamiczone', handler);
}
};
});
export { traverseFactory as default };
//# sourceMappingURL=factory.mjs.map