lib.xp.node.ts Maven / Gradle / Ivy
The newest version!
/**
* Functions to get, query and manipulate nodes.
*
* @example
* var nodeLib = require('/lib/xp/node');
*
* @module node
*/
declare global {
interface XpLibraries {
'/lib/xp/node': typeof import('./node');
}
}
import type {
Aggregation,
Aggregations,
AggregationsResult,
AggregationsToAggregationResults,
ByteSource,
Filter,
Highlight,
HighlightResult,
PrincipalKey,
QueryDsl,
SortDsl,
} from '@enonic-types/core';
export type {
Aggregation,
Aggregations,
AggregationsResult,
BooleanDslExpression,
BooleanFilter,
Bucket,
BucketsAggregationResult,
BucketsAggregationsUnion,
ByteSource,
DateBucket,
DateHistogramAggregation,
DateRange,
DateRangeAggregation,
DistanceUnit,
DslOperator,
DslQueryType,
ExistsDslExpression,
ExistsFilter,
FieldSortDsl,
Filter,
FulltextDslExpression,
GeoDistanceAggregation,
GeoDistanceSortDsl,
GroupKey,
HasValueFilter,
Highlight,
HighlightResult,
HistogramAggregation,
IdsFilter,
InDslExpression,
LikeDslExpression,
MatchAllDslExpression,
MaxAggregation,
MinAggregation,
NgramDslExpression,
NotExistsFilter,
NumericBucket,
NumericRange,
NumericRangeAggregation,
PathMatchDslExpression,
PrincipalKey,
QueryDsl,
RangeDslExpression,
RoleKey,
SingleValueMetricAggregationResult,
SingleValueMetricAggregationsUnion,
SortDirection,
SortDsl,
StatsAggregation,
StatsAggregationResult,
StemmedDslExpression,
TermDslExpression,
TermsAggregation,
UserKey,
ValueCountAggregation,
ValueType,
} from '@enonic-types/core';
type WithRequiredProperty = T & { [P in K]-?: T[P] };
function checkRequired(obj: T, name: keyof T): void {
if (obj == null || obj[name] == null) {
throw `Parameter '${String(name)}' is required`;
}
}
export interface TermSuggestion {
text: string;
term: TermSuggestionOptions;
}
export interface TermSuggestionOptions {
field: string;
analyzer?: string;
sort?: 'score' | 'frequency';
suggestMode?: 'missing' | 'popular' | 'always';
stringDistance?: 'internal' | 'damerau_levenshtein' | 'levenshtein' | 'jarowinkler' | 'ngram';
size?: number | null;
maxEdits?: number | null;
prefixLength?: number | null;
minWordLength?: number | null;
maxInspections?: number | null;
minDocFreq?: number | null;
maxTermFreq?: number | null;
}
export interface Explanation {
value: number;
description: string;
details: Explanation[];
}
export interface NodeQueryResultHit {
id: string;
score: number;
explanation?: Explanation;
highlight?: HighlightResult;
}
export interface SuggestionResult {
text: string;
length: number;
offset: number;
options: {
text: string;
score: number;
freq?: number; // only for term
}[];
}
export interface NodeQueryResult | undefined = undefined> {
total: number;
count: number;
hits: NodeQueryResultHit[];
aggregations: AggregationOutput;
suggestions?: Record;
}
export interface NodeMultiRepoQueryResult | undefined = undefined> {
total: number;
count: number;
hits: (NodeQueryResultHit & {
repoId: string;
branch: string;
})[];
aggregations: AggregationOutput;
suggestions?: Record;
}
interface NodeHandleFactory {
create(context: NodeHandleContext): NodeHandler;
}
interface MultiRepoNodeHandleContext {
addSource(repoId: string, branch: string, principals: PrincipalKey[]): void;
}
interface MultiRepoNodeHandleFactory {
create(context: MultiRepoNodeHandleContext): MultiRepoNodeHandler;
}
const factory = __.newBean('com.enonic.xp.lib.node.NodeHandleFactory');
const multiRepoConnectFactory = __.newBean('com.enonic.xp.lib.node.MultiRepoNodeHandleFactory');
function argsToStringArray(argsArray: (string | string[])[]): string[] {
const array: string[] = [];
for (let i = 0; i < argsArray.length; i++) {
const currArgument = argsArray[i];
if (Array.isArray(currArgument)) {
currArgument.forEach((v) => {
array.push(v);
});
} else {
array.push(currArgument);
}
}
return array;
}
const isString = (value: unknown): value is string => value instanceof String || typeof value === 'string';
function isObject(value: unknown): value is object {
return typeof value !== 'undefined' && value !== null && typeof value === 'object' && value.constructor === Object;
}
function prepareGetParams(params: (string | GetNodeParams | (string | GetNodeParams)[])[], bean: GetNodeHandlerParams): void {
params.forEach(param => {
if (isString(param)) {
bean.add(param);
} else if (Array.isArray(param)) {
prepareGetParams(param, bean);
} else if (isObject(param)) {
checkRequired(param, 'key');
bean.add(param.key, __.nullOrValue(param.versionId));
} else {
throw 'Unsupported type';
}
});
}
interface MultiRepoNodeHandler {
query<
AggregationInput extends Record = never
>(params: QueryNodeHandlerParams): NodeMultiRepoQueryResult>;
}
interface NodeHandler {
create(node: ScriptValue): Node;
modify(editor: ScriptValue, key: string): Node;
setChildOrder(key: string, childOrder: string): Node;
get(params: GetNodeHandlerParams): Node | Node[] | null;
delete(keys: string[]): string[];
push(params: PushNodeHandlerParams): PushNodesResult;
diff(params: DiffBranchesHandlerParams): DiffBranchesResult;
move(source: string, target: string): boolean;
query<
AggregationInput extends Aggregations = never
>(params: QueryNodeHandlerParams): NodeQueryResult>;
exist(key: string): boolean;
findVersions(params: FindVersionsHandlerParams): NodeVersionsQueryResult;
getActiveVersion(key: string): NodeVersion | null;
setActiveVersion(key: string, versionId: string): boolean;
findChildren(params: FindChildrenHandlerParams): FindNodesByParentResult;
commit(keys: string[], message?: string | null): NodeCommit;
getCommit(commitId: string): NodeCommit | null;
setRootPermissions(v: ScriptValue): Node;
getBinary(key: string, binaryReference?: string | null): ByteSource;
refresh(mode: RefreshMode): void;
duplicate(params: DuplicateNodeHandlerParams): Node;
}
export type CreateNodeParams = NodePropertiesOnCreate & NodeData;
export interface ModifyNodeParams {
key: string;
editor: (node: Node) => ModifiedNode;
}
export interface GetNodeParams {
key: string;
versionId?: string;
}
interface GetNodeHandlerParams {
add(key: string): void;
add(key: string, versionId?: string | null): void;
}
export interface PushNodeParams {
key?: string | null;
keys?: string[] | null;
target: string;
includeChildren?: boolean;
resolve?: boolean;
exclude?: string[] | null;
}
export interface PushNodesResult {
success: string[];
failed: {
id: string;
reason: string;
}[];
deleted: string[];
}
interface PushNodeHandlerParams {
setKey(value?: string | null): void;
setKeys(value?: string[] | null): void;
setTargetBranch(value: string): void;
setIncludeChildren(value: boolean): void;
setExclude(value?: string[] | null): void;
setResolve(value: boolean): void;
}
export interface DiffBranchesParams {
key: string;
target: string;
includeChildren: boolean;
}
export interface DiffBranchesResult {
diff: {
id: string;
status: string;
}[];
}
interface DiffBranchesHandlerParams {
setKey(value: string): void;
setTargetBranch(value: string): void;
setIncludeChildren(value: boolean): void;
}
export interface GetBinaryParams {
key: string;
binaryReference?: string | null;
}
export interface MoveNodeParams {
source: string;
target: string;
}
export interface SetChildOrderParams {
key: string;
childOrder: string;
}
export interface QueryNodeParams {
start?: number;
count?: number;
query?: QueryDsl | string;
sort?: string | SortDsl | SortDsl[];
filters?: Filter | Filter[];
aggregations?: AggregationInput;
suggestions?: Record;
highlight?: Highlight;
explain?: boolean;
}
interface QueryNodeHandlerParams {
setStart(value?: number | null): void;
setCount(value?: number | null): void;
setQuery(value: ScriptValue): void;
setSort(value: ScriptValue): void;
setAggregations(value: ScriptValue): void;
setSuggestions(value: ScriptValue): void;
setHighlight(value: ScriptValue): void;
setFilters(value: ScriptValue): void;
setExplain(value: boolean): void;
}
export interface FindVersionsParams {
key: string;
start?: number | null;
count?: number | null;
}
interface FindVersionsHandlerParams {
setKey(key: string): void;
setStart(start?: number | null): void;
setCount(count?: number | null): void;
}
export interface NodeVersion {
versionId: string;
nodeId: string;
nodePath: string;
timestamp: string;
commitId?: string;
}
export interface NodeVersionsQueryResult {
total: number;
count: number;
hits: NodeVersion[];
}
export interface GetActiveVersionParams {
key: string;
}
export interface SetActiveVersionParams {
key: string;
versionId: string;
}
export interface FindChildrenParams {
parentKey: string;
start?: number | null;
count?: number | null;
childOrder?: string;
countOnly?: boolean;
recursive?: boolean;
}
interface FindChildrenHandlerParams {
setParentKey(parentKey: string): void;
setStart(start?: number | null): void;
setCount(count?: number | null): void;
setChildOrder(childOrder: string): void;
setCountOnly(countOnly: boolean): void;
setRecursive(recursive: boolean): void;
}
export interface DuplicateParams> {
nodeId: string;
name?: string;
parent?: string;
includeChildren?: boolean
dataProcessor?: (v: NodeData) => NodeData;
refresh?: RefreshMode;
}
interface DuplicateNodeHandlerParams {
setNodeId(value: string): void;
setName(value?: string): void;
setParent(value?: string): void;
setIncludeChildren(value: boolean): void;
setDataProcessor(value?: ScriptValue): void;
setRefresh(value?: string): void;
}
export interface FindNodesByParentResult {
total: number;
count: number;
hits: {
id: string;
}[];
}
export type RefreshMode = 'SEARCH' | 'STORAGE' | 'ALL';
export interface GetCommitParams {
id: string;
}
export interface NodeCommit {
id: string;
message: string;
committer: string;
timestamp: string;
}
export interface CommitParams {
keys: string | string[];
message?: string;
}
export interface SetRootPermissionsParams {
_permissions: AccessControlEntry[];
_inheritsPermissions: boolean;
}
export type Permission = 'READ' | 'CREATE' | 'MODIFY' | 'DELETE' | 'PUBLISH' | 'READ_PERMISSIONS' | 'WRITE_PERMISSIONS';
export interface AccessControlEntry {
principal: PrincipalKey;
allow?: Permission[];
deny?: Permission[];
}
export interface NodeIndexConfig {
analyzer?: string;
default?: NodeConfigEntry;
configs: {
path: string;
config: NodeConfigEntry;
}[];
}
export type NodeIndexConfigTemplates =
| 'none'
| 'byType'
| 'fulltext'
| 'path'
| 'minimal';
export interface NodeIndexConfigParams {
analyzer?: string;
default?: Partial | NodeIndexConfigTemplates;
configs?: {
path: string;
config: Partial | NodeIndexConfigTemplates;
}[];
}
export interface NodeConfigEntry {
decideByType: boolean;
enabled: boolean;
nGram: boolean;
fulltext: boolean;
includeInAllText: boolean;
path: boolean;
indexValueProcessors: string[];
languages: string[];
}
export type CommonNodeProperties = {
_childOrder: string;
// _id: string; // Not on create
// _indexConfig: Partial | NodeIndexConfigParams | NodeIndexConfig; // Different on read vs write
_inheritsPermissions: boolean;
_manualOrderValue?: number; // Notice optional
_name: string;
_nodeType: string;
// _parentPath?: string; // Only on create
_path: string;
_permissions: AccessControlEntry[];
_state: string;
_ts: string;
_versionKey: string;
};
export type NodePropertiesOnCreate = Partial & {
_indexConfig?: Partial;
_parentPath?: string;
};
export type NodePropertiesOnModify = CommonNodeProperties & {
_id: string;
_indexConfig: NodeIndexConfigParams;
_parentPath?: never;
};
export type NodePropertiesOnRead = CommonNodeProperties & {
_id: string;
_indexConfig: NodeIndexConfig;
_parentPath?: never;
};
export type ModifiedNode> = NodePropertiesOnModify & Data;
export type Node> = NodePropertiesOnRead & Data;
export interface RepoConnection {
create>(params: CreateNodeParams): Node;
modify>(params: ModifyNodeParams): Node;
get>(key: string | GetNodeParams): Node | null;
get>(keys: (string | GetNodeParams)[]): Node | Node[] | null;
get>(...keys: (string | GetNodeParams | (string | GetNodeParams)[])[]): Node | Node[] | null;
delete(...keys: (string | string[])[]): string[];
push(params: PushNodeParams): PushNodesResult;
diff(params: DiffBranchesParams): DiffBranchesResult;
getBinary(params: GetBinaryParams): ByteSource;
move(params: MoveNodeParams): boolean;
setChildOrder>(params: SetChildOrderParams): Node;
query<
AggregationInput extends Aggregations = never
>(params: QueryNodeParams): NodeQueryResult>;
exists(key: string): boolean;
findVersions(params: FindVersionsParams): NodeVersionsQueryResult;
getActiveVersion(params: GetActiveVersionParams): NodeVersion | null;
setActiveVersion(params: SetActiveVersionParams): boolean;
findChildren(params: FindChildrenParams): FindNodesByParentResult;
refresh(mode?: RefreshMode): void;
setRootPermissions>(params: SetRootPermissionsParams): Node;
commit(params: CommitParams): NodeCommit;
getCommit(params: GetCommitParams): NodeCommit | null;
duplicate>(params: DuplicateParams): Node;
}
/**
* Creates a new repo connection.
*
* @constructor
* @hideconstructor
* @alias RepoConnection
*/
class RepoConnectionImpl
implements RepoConnection {
constructor(private nodeHandler: NodeHandler) {
}
/**
* This function creates a node.
*
*
* To create a content where the name is not important and there could be multiple instances under the same parent content,
* skip the `name` parameter and specify a `displayName`.
*
* @example-ref examples/node/create-1.js
* @example-ref examples/node/create-2.js
*
* @param {object} params JSON with the parameters.
* @param {string} [params._name] Name of content.
* @param {string} [params._parentPath] Path to place content under.
* @param {object} [params._indexConfig] How the document should be indexed. A default value "byType" will be set if no value specified.
* @param {object} [params._permissions] The access control list for the node. By the default the creator will have full access
* @param {boolean} [params._inheritsPermissions] true if the permissions should be inherited from the node parent. Default is false.
* @param {number} [params._manualOrderValue] Value used to order document when ordering by parent and child-order is set to manual
* @param {string} [params._childOrder] Default ordering of children when doing getChildren if no order is given in query
*
* @returns {object} Node created as JSON.
*/
create>(params: CreateNodeParams): Node {
return __.toNativeObject(this.nodeHandler.create(__.toScriptValue(params)));
}
/**
* This function modifies a node.
*
* @example-ref examples/node/modify.js
*
* @param {object} params JSON with the parameters.
* @param {string} params.key Path or id to the node.
* @param {function} params.editor Editor callback function.
*
* @returns {object} Modified node as JSON.
*/
modify>(params: ModifyNodeParams): Node {
checkRequired(params, 'key');
return __.toNativeObject(this.nodeHandler.modify(__.toScriptValue(params.editor), params.key));
}
get>(keys: string | GetNodeParams): Node | null;
get>(keys: (string | GetNodeParams)[]): Node[] | null;
get>(...keys: (string | GetNodeParams | (string | GetNodeParams)[])[]): Node[] | null;
/**
* This function fetches nodes.
*
* @example-ref examples/node/get-1.js
* @example-ref examples/node/get-2.js
* @example-ref examples/node/get-3.js
*
* @param {...(string|object|Array.<(string|object)>)} keys to fetch. Each argument could be an id, a path, an object with key and versionId properties or an array of them.
*
* @returns {object} The node or node array (as JSON) fetched from the repository.
*/
get>(...keys: (string | GetNodeParams | (string | GetNodeParams)[])[]): Node | Node[] | null {
const handlerParams = __.newBean('com.enonic.xp.lib.node.GetNodeHandlerParams');
prepareGetParams(keys, handlerParams);
return __.toNativeObject(this.nodeHandler.get(handlerParams));
}
/**
* This function deletes a node or nodes.
*
* @example-ref examples/node/delete.js
*
* @param {...(string|string[])} keys Keys to delete. Each argument could be an id, a path or an array of the two
*
* @returns {string[]} An array of keys that were actually deleted
*/
delete(...keys: (string | string[])[]): string[] {
return __.toNativeObject(this.nodeHandler.delete(argsToStringArray(keys)));
}
/**
* This function push a node to a given branch.
*
* @example-ref examples/node/push-1.js
* @example-ref examples/node/push-2.js
* @example-ref examples/node/push-3.js
*
* @param {object} params JSON with the parameters
* @param {string} params.key Id or path to the nodes
* @param {string[]} params.keys Array of ids or paths to the nodes
* @param {string} params.target Branch to push nodes to
* @param {boolean} [params.includeChildren=false] Also push children of given nodes
* @param {boolean} [params.resolve=true] Resolve dependencies before pushing, meaning that references will also be pushed
* @param {string[]} [params.exclude] Array of ids or paths to nodes not to be pushed (nodes needed to maintain data integrity (e.g parents must be present in target) will be pushed anyway)
*
* @returns {object} PushNodesResult
*/
push(params: PushNodeParams): PushNodesResult {
checkRequired(params, 'target');
const {
key,
keys,
target,
includeChildren = false,
resolve = true,
exclude,
} = params ?? {};
if (typeof key === 'undefined' && typeof keys === 'undefined') {
throw "Parameter key' or 'keys' is required";
}
const handlerParams = __.newBean('com.enonic.xp.lib.node.PushNodeHandlerParams');
handlerParams.setKey(__.nullOrValue(key));
handlerParams.setKeys(__.nullOrValue(keys));
handlerParams.setTargetBranch(target);
handlerParams.setIncludeChildren(includeChildren);
handlerParams.setExclude(__.nullOrValue(exclude));
handlerParams.setResolve(resolve);
return __.toNativeObject(this.nodeHandler.push(handlerParams));
}
/**
* This function resolves the differences for node between current and given branch
*
* @example-ref examples/node/diff-1.js
*
* @param {object} params JSON with the parameters.
* @param {string} params.key Path or id to resolve diff for
* @param {string} params.target Branch to diff against.
* @param {boolean} [params.includeChildren=false] also resolve dependencies for children
*
* @returns {object} DiffNodesResult
*/
diff(params: DiffBranchesParams): DiffBranchesResult {
const {
key,
target,
includeChildren = false,
} = params ?? {};
const handlerParams = __.newBean('com.enonic.xp.lib.node.DiffBranchesHandlerParams');
handlerParams.setKey(key);
handlerParams.setTargetBranch(target);
handlerParams.setIncludeChildren(includeChildren);
return __.toNativeObject(this.nodeHandler.diff(handlerParams));
}
/**
* This function returns a binary stream.
*
* @example-ref examples/node/getBinary.js
* @param {string} params.key Path or id to the node.
* @param {string} params.binaryReference to the binary.
*
* @returns {*} Stream of the binary.
*/
getBinary(params: GetBinaryParams): ByteSource {
checkRequired(params, 'key');
return this.nodeHandler.getBinary(params.key, params.binaryReference);
}
/**
* Rename a node or move it to a new path.
*
* @example-ref examples/node/move-1.js
* @example-ref examples/node/move-2.js
* @example-ref examples/node/move-3.js
*
* @param {object} params JSON with the parameters.
* @param {string} params.source Path or id of the node to be moved or renamed.
* @param {string} params.target New path or name for the node. If the target ends in slash '/', it specifies the parent path where to be moved. Otherwise it means the new desired path or name for the node.
*
* @returns {boolean} True if the node was successfully moved or renamed, false otherwise.
*/
move(params: MoveNodeParams): boolean {
checkRequired(params, 'source');
checkRequired(params, 'target');
return __.toNativeObject(this.nodeHandler.move(params.source, params.target));
}
/**
* Set node's children order
*
* @example-ref examples/node/setChildOrder.js
*
* @param {object} params JSON with the parameters.
* @param {string} params.key node's path or id
* @param {string} params.childOrder children order
* @returns {object} updated node
*/
setChildOrder>(params: SetChildOrderParams): Node {
checkRequired(params, 'key');
checkRequired(params, 'childOrder');
return __.toNativeObject(this.nodeHandler.setChildOrder(params.key, params.childOrder));
}
/**
* This command queries nodes.
*
* @example-ref examples/node/query.js
*
* @param {object} params JSON with the parameters.
* @param {number} [params.start=0] Start index (used for paging).
* @param {number} [params.count=10] Number of contents to fetch.
* @param {string|object} [params.query] Query expression.
* @param {object} [params.filters] Query filters
* @param {string|object|object[]} [params.sort='_score DESC'] Sorting expression.
* @param {string} [params.aggregations] Aggregations expression.
* @param {string} [params.highlight] Highlighting parameters.
* @param {boolean} [params.explain=false] Return score calculation explanation.
* @returns {object} Result of query.
*/
query<
AggregationInput extends Aggregations = never
>(params: QueryNodeParams): NodeQueryResult> {
const {
start = 0,
count = 10,
query,
sort,
aggregations,
suggestions,
highlight,
filters,
explain = false,
} = params ?? {};
const handlerParams = __.newBean('com.enonic.xp.lib.node.QueryNodeHandlerParams');
handlerParams.setStart(start);
handlerParams.setCount(count);
handlerParams.setQuery(__.toScriptValue((query)));
handlerParams.setSort(__.toScriptValue(sort));
handlerParams.setAggregations(__.toScriptValue(aggregations));
handlerParams.setSuggestions(__.toScriptValue(suggestions));
handlerParams.setHighlight(__.toScriptValue(highlight));
handlerParams.setFilters(__.toScriptValue(filters));
handlerParams.setExplain(explain);
return __.toNativeObject(this.nodeHandler.query(handlerParams));
}
/**
* Check if node exists.
*
* @example-ref examples/node/exists.js
*
* @param {string} [key] node path or id.
*
* @returns {boolean} True if exists, false otherwise.
*/
exists(key: string): boolean {
return __.toNativeObject(this.nodeHandler.exist(key));
}
/**
* This function returns node versions.
*
* @example-ref examples/node/findVersions.js
* @param {object} params JSON parameters.
* @param {string} params.key Path or ID of the node.
* @param {number} [params.start=0] Start index (used for paging).
* @param {number} [params.count=10] Number of node versions to fetch.
*
* @returns {object[]} Node versions.
*/
findVersions(params: FindVersionsParams): NodeVersionsQueryResult {
checkRequired(params, 'key');
const {
key,
start = 0,
count = 10,
} = params ?? {};
const handlerParams = __.newBean('com.enonic.xp.lib.node.FindVersionsHandlerParams');
handlerParams.setKey(key);
handlerParams.setStart(start);
handlerParams.setCount(count);
return __.toNativeObject(this.nodeHandler.findVersions(handlerParams));
}
/**
* This function returns the active version of a node.
*
* @example-ref examples/node/getActiveVersion.js
* @param {object} params JSON parameters.
* @param {string} params.key Path or ID of the node.
*
* @returns {object} Active content versions per branch.
*/
getActiveVersion(params: GetActiveVersionParams): NodeVersion | null {
checkRequired(params, 'key');
return __.toNativeObject(this.nodeHandler.getActiveVersion(params.key));
}
/**
* This function sets the active version of a node.
*
* @example-ref examples/node/setActiveVersion.js
* @param {object} params JSON parameters.
* @param {string} params.key Path or ID of the node.
* @param {string} params.versionId Version to set as active.
*
* @returns {boolean} True if deleted, false otherwise.
*/
setActiveVersion(params: SetActiveVersionParams): boolean {
checkRequired(params, 'key');
checkRequired(params, 'versionId');
return __.toNativeObject(this.nodeHandler.setActiveVersion(params.key, params.versionId));
}
/**
* Get children for given node.
*
* @example-ref examples/node/findChildren.js
*
* @param {object} params JSON with the parameters.
* @param {number} params.parentKey path or id of parent to get children of
* @param {number} [params.start=0] Start index (used for paging).
* @param {number} [params.count=10] Number of contents to fetch.
* @param {string} [params.childOrder] How to order the children (defaults to value stored on parent)
* @param {boolean} [params.countOnly=false] Optimize for count children only ( no children returned )
* @param {boolean} [params.recursive=false] Do recursive fetching of all children of children
* @returns {object} Result of getChildren.
*/
findChildren(params: FindChildrenParams): FindNodesByParentResult {
checkRequired(params, 'parentKey');
const {
parentKey,
start = 0,
count = 10,
childOrder,
countOnly = false,
recursive = false,
} = params ?? {};
const handlerParams = __.newBean('com.enonic.xp.lib.node.FindChildrenHandlerParams');
handlerParams.setParentKey(parentKey);
handlerParams.setStart(start);
handlerParams.setCount(count);
handlerParams.setChildOrder(childOrder);
handlerParams.setCountOnly(countOnly);
handlerParams.setRecursive(recursive);
return __.toNativeObject(this.nodeHandler.findChildren(handlerParams));
}
/**
* Refresh the index for the current repoConnection
*
* @example-ref examples/node/refresh.js
*
* @param {string} [mode]=ALL Refresh all (ALL) data, or just the search-index (SEARCH), or the storage-index (STORAGE)
*/
refresh(mode: RefreshMode = 'ALL'): void {
this.nodeHandler.refresh(mode);
}
/**
* Set the root node permissions and inherit.
*
* @example-ref examples/node/modifyRootPermissions.js
*
* @param {object} params JSON with the parameters.
* @param {object} params._permissions the permission json
* @param {object} [params._inheritsPermissions]= true if the permissions should be inherited to children
*
* @returns {object} Updated root-node as JSON.
*/
setRootPermissions>(params: SetRootPermissionsParams): Node {
checkRequired(params, '_permissions');
return __.toNativeObject(this.nodeHandler.setRootPermissions(__.toScriptValue(params)));
}
/**
* This function commits the active version of nodes.
*
* @example-ref examples/node/commit.js
*
* @param {...(string|string[])} params.keys Node keys to commit. Each argument could be an id, a path or an array of the two. Prefer the usage of ID rather than paths.
* @param {string} [params.message] Commit message.
*
* @returns {object} Commit object.
*/
commit(params: CommitParams): NodeCommit {
const keys: string[] = Array.isArray(params.keys) ? params.keys : [params.keys];
return __.toNativeObject(this.nodeHandler.commit(argsToStringArray(keys), __.nullOrValue(params.message)));
}
/**
* This function fetches commit by id.
*
* @example-ref examples/node/commit.js
*
* @param {string} params.id existing commit id.
*
* @returns {object} Commit object.
*/
getCommit(params: GetCommitParams): NodeCommit | null {
checkRequired(params, 'id');
return __.toNativeObject(this.nodeHandler.getCommit(params.id));
}
/**
* This function duplicates a node.
*
* @example-ref examples/node/duplicate.js
*
* @param {object} params JSON parameters.
* @param {string} params.nodeId Id to the node.
* @param {string} [params.name] New node name.
* @param {boolean} [params.includeChildren=true] Indicates that children nodes must be duplicated, too.
* @param {string} [params.parent] Destination parent path. By default, a duplicated node will be added as a sibling of the source node.
* @param {string} [params.refresh] Refresh the index for the current repoConnection.
* @param {function} [params.dataProcessor] Node data processor.
*
* @returns {object} Duplicated node.
*/
duplicate>(params: DuplicateParams): Node {
checkRequired(params, 'nodeId');
const {
nodeId,
name,
includeChildren = true,
parent,
dataProcessor,
refresh,
} = params ?? {};
const handlerParams = __.newBean('com.enonic.xp.lib.node.DuplicateNodeHandlerParams');
handlerParams.setNodeId(nodeId);
handlerParams.setIncludeChildren(includeChildren);
handlerParams.setName(__.nullOrValue(name));
handlerParams.setParent(__.nullOrValue(parent));
handlerParams.setRefresh(__.nullOrValue(refresh));
handlerParams.setDataProcessor(__.toScriptValue(dataProcessor));
return __.toNativeObject(this.nodeHandler.duplicate(handlerParams));
}
}
export interface MultiRepoConnection {
query<
AggregationInput extends Aggregations = never
>(params: QueryNodeParams): NodeMultiRepoQueryResult>;
}
/**
* Creates a new multirepo-connection.
*
* @constructor
* @hideconstructor
* @alias MultiRepoConnection
*/
class MultiRepoConnectionImpl
implements MultiRepoConnection {
constructor(private multiRepoConnection: MultiRepoNodeHandler) {
}
/**
* This command queries nodes in a multi-repo connection.
*
* @example-ref examples/node/multiRepoQuery.js
*
* @param {object} params JSON with the parameters.
* @param {number} [params.start=0] Start index (used for paging).
* @param {number} [params.count=10] Number of contents to fetch.
* @param {string|object} [params.query] Query expression.
* @param {object} [params.filters] Query filters
* @param {string|object|object[]} [params.sort='_score DESC'] Sorting expression.
* @param {string} [params.aggregations] Aggregations expression.
* @param {string} [params.highlight] Highlighting parameters.
* @param {boolean} [params.explain=false] Return score calculation explanation.
* @returns {object} Result of query.
*/
query<
AggregationInput extends Aggregations = never
>(params: QueryNodeParams): NodeMultiRepoQueryResult> {
const {
start = 0,
count = 10,
query,
sort,
aggregations,
suggestions,
highlight,
filters,
explain = false,
} = params ?? {};
const handlerParams = __.newBean('com.enonic.xp.lib.node.QueryNodeHandlerParams');
handlerParams.setStart(start);
handlerParams.setCount(count);
handlerParams.setQuery(__.toScriptValue((query)));
handlerParams.setSort(__.toScriptValue(sort));
handlerParams.setAggregations(__.toScriptValue(aggregations));
handlerParams.setSuggestions(__.toScriptValue(suggestions));
handlerParams.setHighlight(__.toScriptValue(highlight));
handlerParams.setFilters(__.toScriptValue(filters));
handlerParams.setExplain(explain);
return __.toNativeObject(this.multiRepoConnection.query(handlerParams));
}
}
export interface ConnectParams {
repoId: string;
branch: string;
principals?: PrincipalKey[];
user?: {
login: string;
idProvider?: string;
};
}
interface NodeHandleContext {
setRepoId(value: string): void;
setBranch(value: string): void;
setUsername(value: string): void;
setIdProvider(value: string): void;
setPrincipals(value: string[] | null): void;
}
/**
* Creates a connection to a repository with a given branch and authentication info.
*
* @example-ref examples/node/connect.js
*
* @param {object} params JSON with the parameters.
* @param {object} params.repoId repository id
* @param {object} params.branch branch id
* @param {object} [params.user] User to execute the callback with. Default is the current user.
* @param {string} params.user.login Login of the user.
* @param {string} [params.user.idProvider] Id provider containing the user. By default, all the id providers will be used.
* @param {string[]} [params.principals] Additional principals to execute the callback with.
* @returns {RepoConnection} Returns a new repo-connection.
*/
export function connect(params: ConnectParams): RepoConnection {
checkRequired(params, 'repoId');
checkRequired(params, 'branch');
const nodeHandleContext = __.newBean('com.enonic.xp.lib.node.NodeHandleContext');
nodeHandleContext.setRepoId(params.repoId);
nodeHandleContext.setBranch(params.branch);
if (params.user) {
if (params.user.login) {
nodeHandleContext.setUsername(params.user.login);
}
if (params.user.idProvider) {
nodeHandleContext.setIdProvider(params.user.idProvider);
}
}
nodeHandleContext.setPrincipals(params.principals ?? null);
return new RepoConnectionImpl(factory.create(nodeHandleContext));
}
export interface MultiRepoConnectParams {
sources: WithRequiredProperty[];
}
/**
* Creates a connection to several repositories with a given branch and authentication info.
*
* @example-ref examples/node/multiRepoConnect.js
*
* @param {object} params JSON with the parameters.
* @param {object[]} params.sources array of sources to connect to
* @param {object} params.sources.repoId repository id
* @param {object} params.sources.branch branch id
* @param {object} [params.sources.user] User to execute the callback with. Default is the current user.
* @param {string} params.sources.user.login Login of the user.
* @param {string} [params.sources.user.idProvider] Id provider containing the user. By default, all the id providers will be used.
* @param {string[]} params.sources.principals Principals to execute the callback with.
*
* @returns {MultiRepoConnection} Returns a new multirepo-connection.
*/
export function multiRepoConnect(params: MultiRepoConnectParams): MultiRepoConnection {
const multiRepoNodeHandleContext = __.newBean('com.enonic.xp.lib.node.MultiRepoNodeHandleContext');
params.sources.forEach((source: ConnectParams) => {
checkRequired(source, 'repoId');
checkRequired(source, 'branch');
checkRequired(source, 'principals');
multiRepoNodeHandleContext.addSource(source.repoId, source.branch, source.principals);
});
return new MultiRepoConnectionImpl(multiRepoConnectFactory.create(multiRepoNodeHandleContext));
}