forest-cli
Version:
The Lumberjacks' toolbelt is the Forest CLI which makes easy to manage your back office application directly from the terminal.
434 lines • 29.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.matchesWhitelist = exports.NUM_OR_UUID = exports.DOMAIN_RULES = void 0;
const scalar = (prop, extra = {}) => ({
kind: 'scalar',
prop,
...extra,
});
const opaque = (prop, extra = {}) => ({
kind: 'opaque',
prop,
...extra,
});
/** Return an addDefaults fn that fills the given keys only when absent. */
const withDefaults = (defaults) => (value) => {
const out = { ...value };
Object.entries(defaults).forEach(([key, fallback]) => {
if (out[key] === undefined)
out[key] = fallback;
});
return out;
};
/**
* Segment write-shape: the rendering read omits `defaultSortingFieldName` and
* `columns` (both required by the server's segment validator), and manual
* segments require `filter`/`query` keys to be present (null allowed) while
* smart segments forbid them.
*/
function segmentAddDefaults(value) {
const out = withDefaults({
columns: [],
defaultSortingFieldName: null,
defaultSortingFieldOrder: null,
hasColumnsConfiguration: false,
icon: null,
isVisible: true,
position: 0,
type: 'manual',
})(value);
if (out.type !== 'smart') {
if (out.filter === undefined)
out.filter = null;
if (out.query === undefined)
out.query = null;
}
return out;
}
/** Chart properties (viewEdit and dashboards) — editable scalars; clear one by setting it to `null`. */
const CHART_PROPS = [
'name',
'type',
'aggregator',
'aggregateFieldName',
'filter',
'query',
'apiVersion',
'sourceCollectionId',
'groupByFieldName',
'timeRange',
'limit',
'labelFieldName',
'relationshipFieldName',
'numeratorChartId',
'denominatorChartId',
'objective',
'displaySettings',
'description',
'subTitle',
].map(prop => scalar(prop));
const SEGMENT_RULE = {
addable: true,
children: [
scalar('name'),
scalar('position'),
scalar('isVisible'),
opaque('filter'),
{
children: [scalar('position'), scalar('isVisible')],
fallbackReplaceWhole: true,
kind: 'keyedArray',
prop: 'columns',
segment: 'columns',
},
],
addDefaults: segmentAddDefaults,
kind: 'keyedArray',
premiumPack: 'scopes',
prop: 'segments',
removable: true,
segment: 'segments',
};
/** Children of a collection's `layout` object (canonical: collection.layout.*). */
const COLLECTION_LAYOUT_RULE = {
children: [
{
children: [scalar('position'), scalar('isVisible')],
kind: 'keyedArray',
prop: 'columns',
segment: 'columns',
},
{
children: [
scalar('displayName'),
scalar('description'),
scalar('isReadOnly'),
scalar('isFilterDisplayed'),
scalar('isDissociateDisplayed'),
opaque('widgetEdit'),
opaque('widgetDisplay'),
opaque('mappingValues'),
opaque('conditionalFormatting'),
],
kind: 'keyedArray',
prop: 'fields',
segment: 'fields',
},
SEGMENT_RULE,
{
children: [
scalar('position'),
scalar('isVisible'),
scalar('displayName'),
opaque('confirmation'),
opaque('segments'),
scalar('buttonType'),
],
kind: 'keyedArray',
prop: 'actions',
segment: 'actions',
},
{
children: [
opaque('summaryView'),
{
addable: true,
children: CHART_PROPS,
kind: 'keyedArray',
prop: 'charts',
removable: true,
segment: 'charts',
stripOnAdd: [],
},
],
kind: 'object',
prop: 'viewEdit',
segment: 'viewEdit',
},
],
kind: 'object',
prop: 'layout',
segment: 'layout',
};
const COLLECTION_RULES = [
scalar('displayName'),
scalar('displayNamePlural'),
scalar('icon'),
scalar('restrictedToSegments'),
scalar('defaultSortingOrder'),
scalar('defaultSortingFieldName'),
scalar('displayFieldName'),
COLLECTION_LAYOUT_RULE,
];
/**
* Workspaces (and their components) — addressed by id (the route's
* `:collectionId` param receives the workspace/component id). Component `type` is
* add-only (set on creation); `name`, `displaySettings`, `visibility` and
* `options` are editable, matching the server whitelist. `options` is deep and
* polymorphic (filter, visibleColumns, collectionId…), so it is kept opaque and
* replaced as a whole when it changes.
*/
const WORKSPACE_RULE = {
addable: true,
addDefaults: withDefaults({ collectionId: null, components: [], icon: '🗂️', position: 0 }),
children: [
scalar('name'),
scalar('icon'),
scalar('position'),
{
addable: true,
children: [
scalar('name'),
opaque('displaySettings'),
opaque('visibility'),
opaque('options'),
],
kind: 'keyedArray',
prop: 'components',
removable: true,
segment: 'components',
},
],
kind: 'keyedArray',
prop: 'workspaces',
removable: true,
segment: 'workspaces',
};
/**
* Inboxes — premium-gated. `type`, `dispatchRule`, `sortingFields`,
* `collectionId` and `segmentId` are add-only (set on creation, not
* replaceable); the rest are editable scalars.
*/
const INBOX_RULE = {
addable: true,
addDefaults: withDefaults({ canUsersReassign: false, position: 0 }),
children: [
scalar('name'),
scalar('icon'),
scalar('position'),
scalar('folder'),
scalar('tasksLimit'),
scalar('canUsersReassign'),
opaque('unassignAfter'),
],
kind: 'keyedArray',
premiumPack: 'inbox',
prop: 'inboxes',
removable: true,
segment: 'inboxes',
};
exports.DOMAIN_RULES = {
folders: {
root: [
{
addable: true,
children: [
scalar('name'),
scalar('icon'),
{
addable: true,
children: [
scalar('position'),
scalar('isVisible'),
{
addable: true,
children: [scalar('position'), scalar('isVisible')],
kind: 'keyedArray',
prop: 'subChildren',
removable: true,
segment: 'subChildren',
},
],
kind: 'keyedArray',
prop: 'children',
removable: true,
segment: 'children',
},
],
kind: 'keyedArray',
prop: '',
removable: true,
segment: 'folders',
singletonFlag: 'isMain',
},
],
},
layout: {
root: [
{
children: COLLECTION_RULES,
kind: 'keyedArray',
prop: 'collections',
segment: 'collections',
},
{
addable: true,
children: [
scalar('name'),
scalar('icon'),
scalar('position'),
{
addable: true,
children: CHART_PROPS,
kind: 'keyedArray',
prop: 'charts',
removable: true,
segment: 'charts',
stripOnAdd: [],
},
],
addDefaults: withDefaults({ charts: [], icon: null, position: 0 }),
kind: 'keyedArray',
premiumPack: 'multipleDashboards',
prop: 'dashboards',
removable: true,
segment: 'dashboards',
},
WORKSPACE_RULE,
INBOX_RULE,
opaque('sections'),
],
},
workflows: {
root: [
{
addable: true,
// `collectionId` is required on add but is not a replaceable path, so it is
// carried in the add value (passed through) rather than declared as a child.
addDefaults: withDefaults({ isVisible: true, position: 0, segmentIds: [] }),
children: [
scalar('name'),
scalar('position'),
scalar('isVisible'),
opaque('segmentIds'),
scalar('bpmnAwsS3Identifier'),
],
kind: 'keyedArray',
prop: '',
removable: true,
segment: 'workflows',
// `steps` is authoring input compiled to BPMN out-of-band, never sent in the shell patch.
stripOnAdd: ['steps'],
},
],
},
};
/* --------------------------- whitelist mirror ---------------------------- */
// Same id classes as the server's patch-handler. NUM_OR_UUID is exported so the
// sidecar prune (`workflow-sidecar.ts`) only ever deletes files named after a
// real server id — never a user's own hand-named BPMN files.
const ID = String.raw `[^/\s:]+`;
exports.NUM_OR_UUID = String.raw `([0-9]+|[0-9a-fA-F-]{36})`;
function entry(ops, path) {
return { ops, pattern: new RegExp(`^${path}$`) };
}
const COLLECTION_SCALARS = [
'displayName',
'displayNamePlural',
'icon',
'restrictedToSegments',
'defaultSortingOrder',
'defaultSortingFieldName',
'displayFieldName',
].join('|');
const FIELD_PROPS = [
'displayName',
'description',
'isReadOnly',
'isFilterDisplayed',
'isDissociateDisplayed',
'widgetEdit',
'widgetDisplay',
'mappingValues',
'conditionalFormatting',
].join('|');
const ACTION_PROPS = [
'position',
'isVisible',
'displayName',
'confirmation',
'segments',
'buttonType',
].join('|');
const CHART_PROP_NAMES = [
'name',
'type',
'aggregator',
'aggregateFieldName',
'filter',
'query',
'apiVersion',
'sourceCollectionId',
'groupByFieldName',
'timeRange',
'limit',
'labelFieldName',
'relationshipFieldName',
'numeratorChartId',
'denominatorChartId',
'objective',
'displaySettings',
'description',
'subTitle',
].join('|');
const WHITELIST = {
folders: [
entry(['add'], `/folders/-`),
entry(['remove'], `/folders/${exports.NUM_OR_UUID}`),
entry(['replace'], `/folders/${exports.NUM_OR_UUID}/(name|icon)`),
entry(['add'], `/folders/${exports.NUM_OR_UUID}/children/-`),
entry(['remove'], `/folders/${exports.NUM_OR_UUID}/children/${ID}`),
entry(['replace'], `/folders/${exports.NUM_OR_UUID}/children/${ID}/(position|isVisible)`),
entry(['add'], `/folders/${exports.NUM_OR_UUID}/children/${ID}/subChildren/-`),
entry(['remove'], `/folders/${exports.NUM_OR_UUID}/children/${ID}/subChildren/${ID}`),
entry(['replace'], `/folders/${exports.NUM_OR_UUID}/children/${ID}/subChildren/${ID}/(position|isVisible)`),
],
layout: [
entry(['replace'], `/collections/${ID}/(${COLLECTION_SCALARS})`),
entry(['replace'], `/collections/${ID}/layout/columns/${ID}/(position|isVisible)`),
entry(['replace'], `/collections/${ID}/layout/fields/${ID}/(${FIELD_PROPS})`),
entry(['add'], `/collections/${ID}/layout/segments/-`),
entry(['remove'], `/collections/${ID}/layout/segments/${ID}`),
entry(['replace'], `/collections/${ID}/layout/segments/${ID}/(name|position|isVisible|filter|columns)`),
entry(['replace'], `/collections/${ID}/layout/segments/${ID}/columns/${ID}/(position|isVisible)`),
entry(['replace'], `/collections/${ID}/layout/actions/${ID}/(${ACTION_PROPS})`),
entry(['replace'], `/collections/${ID}/layout/viewEdit/summaryView`),
entry(['add'], `/collections/${ID}/layout/viewEdit/charts/-`),
entry(['remove', 'replace'], `/collections/${ID}/layout/viewEdit/charts/${exports.NUM_OR_UUID}`),
entry(['remove', 'replace'], `/collections/${ID}/layout/viewEdit/charts/${exports.NUM_OR_UUID}/(${CHART_PROP_NAMES})`),
entry(['replace'], `/collections/${ID}/layout/viewEdit/rows/${ID}/(position|isVisible|explorerConfiguration)`),
entry(['replace'], `/collections/${ID}/layout/viewCreate/rows/${ID}/(position|isVisible)`),
entry(['add'], `/collections/${ID}/layout/viewLists/-`),
entry(['remove'], `/collections/${ID}/layout/viewLists/${ID}`),
entry(['replace'], `/collections/${ID}/layout/viewLists/${ID}/(name|position|recordsPerPage|allowJavascript)`),
entry(['replace'], `/collections/${ID}/layout/scope`),
entry(['add'], `/dashboards/-`),
entry(['remove'], `/dashboards/${exports.NUM_OR_UUID}`),
entry(['replace'], `/dashboards/${exports.NUM_OR_UUID}/(name|icon|position)`),
entry(['add'], `/dashboards/${exports.NUM_OR_UUID}/charts/-`),
entry(['remove', 'replace'], `/dashboards/${exports.NUM_OR_UUID}/charts/${exports.NUM_OR_UUID}`),
entry(['remove', 'replace'], `/dashboards/${exports.NUM_OR_UUID}/charts/${exports.NUM_OR_UUID}/(${CHART_PROP_NAMES})`),
entry(['add'], `/workspaces/-`),
entry(['remove'], `/workspaces/${ID}`),
entry(['replace'], `/workspaces/${ID}/(name|icon|position)`),
entry(['add'], `/workspaces/${ID}/components/-`),
entry(['remove'], `/workspaces/${ID}/components/${exports.NUM_OR_UUID}`),
entry(['replace'], `/workspaces/${ID}/components/${exports.NUM_OR_UUID}/(name|displaySettings|visibility|options)`),
entry(['add'], `/inboxes/-`),
entry(['remove'], `/inboxes/${exports.NUM_OR_UUID}`),
entry(['replace'], `/inboxes/${exports.NUM_OR_UUID}/${ID}`),
entry(['replace'], `/sections`),
],
workflows: [
entry(['add'], `/workflows/-`),
entry(['remove'], `/workflows/${exports.NUM_OR_UUID}`),
entry(['replace'], `/workflows/${exports.NUM_OR_UUID}/(name|position|isVisible|segmentIds|bpmnAwsS3Identifier)`),
],
};
/** True when an op matches the mirrored server whitelist for this domain. */
function matchesWhitelist(domain, op) {
return WHITELIST[domain].some(candidate => candidate.ops.includes(op.op) &&
candidate.pattern.test(op.path));
}
exports.matchesWhitelist = matchesWhitelist;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGF0Y2gtcnVsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zcmMvc2VydmljZXMvbGF5b3V0L3BhdGNoLXJ1bGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQTREQSxNQUFNLE1BQU0sR0FBRyxDQUFDLElBQVksRUFBRSxRQUE2QixFQUFFLEVBQWMsRUFBRSxDQUFDLENBQUM7SUFDN0UsSUFBSSxFQUFFLFFBQVE7SUFDZCxJQUFJO0lBQ0osR0FBRyxLQUFLO0NBQ1QsQ0FBQyxDQUFDO0FBQ0gsTUFBTSxNQUFNLEdBQUcsQ0FBQyxJQUFZLEVBQUUsUUFBNkIsRUFBRSxFQUFjLEVBQUUsQ0FBQyxDQUFDO0lBQzdFLElBQUksRUFBRSxRQUFRO0lBQ2QsSUFBSTtJQUNKLEdBQUcsS0FBSztDQUNULENBQUMsQ0FBQztBQUVILDJFQUEyRTtBQUMzRSxNQUFNLFlBQVksR0FDaEIsQ0FBQyxRQUFpQyxFQUFFLEVBQUUsQ0FDdEMsQ0FBQyxLQUE4QixFQUEyQixFQUFFO0lBQzFELE1BQU0sR0FBRyxHQUFHLEVBQUUsR0FBRyxLQUFLLEVBQUUsQ0FBQztJQUN6QixNQUFNLENBQUMsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLFFBQVEsQ0FBQyxFQUFFLEVBQUU7UUFDbkQsSUFBSSxHQUFHLENBQUMsR0FBRyxDQUFDLEtBQUssU0FBUztZQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxRQUFRLENBQUM7SUFDbEQsQ0FBQyxDQUFDLENBQUM7SUFFSCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUMsQ0FBQztBQUVKOzs7OztHQUtHO0FBQ0gsU0FBUyxrQkFBa0IsQ0FBQyxLQUE4QjtJQUN4RCxNQUFNLEdBQUcsR0FBRyxZQUFZLENBQUM7UUFDdkIsT0FBTyxFQUFFLEVBQUU7UUFDWCx1QkFBdUIsRUFBRSxJQUFJO1FBQzdCLHdCQUF3QixFQUFFLElBQUk7UUFDOUIsdUJBQXVC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