@dyrected/core 2.5.29 → 2.5.30
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-CQDVPMEU.js +613 -0
- package/dist/index-DTrpTru7.d.cts +1881 -0
- package/dist/index-DTrpTru7.d.ts +1881 -0
- package/dist/index-DzUlE5Hc.d.cts +1751 -0
- package/dist/index-DzUlE5Hc.d.ts +1751 -0
- package/dist/index-qhLus8ZO.d.cts +1881 -0
- package/dist/index-qhLus8ZO.d.ts +1881 -0
- package/dist/index.cjs +330 -4
- package/dist/index.d.cts +56 -3
- package/dist/index.d.ts +56 -3
- package/dist/index.js +40 -4
- package/dist/server.cjs +482 -156
- package/dist/server.d.cts +28 -1
- package/dist/server.d.ts +28 -1
- package/dist/server.js +232 -158
- package/dist/where-sanitizer-WJ2W2QCE.js +54 -0
- package/package.json +2 -1
package/dist/index.cjs
CHANGED
|
@@ -20,21 +20,43 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
LIFECYCLE_EVENTS_COLLECTION: () => LIFECYCLE_EVENTS_COLLECTION,
|
|
24
|
+
LIFECYCLE_EVENT_NAMES: () => LIFECYCLE_EVENT_NAMES,
|
|
25
|
+
WORKFLOW_HISTORY_COLLECTION: () => WORKFLOW_HISTORY_COLLECTION,
|
|
26
|
+
availableWorkflowTransitions: () => availableWorkflowTransitions,
|
|
27
|
+
createLifecycleEvent: () => createLifecycleEvent,
|
|
28
|
+
createWorkflowDocument: () => createWorkflowDocument,
|
|
23
29
|
defineCollection: () => defineCollection,
|
|
24
30
|
defineConfig: () => defineConfig,
|
|
25
31
|
defineGlobal: () => defineGlobal,
|
|
32
|
+
dispatchLifecycleEvent: () => dispatchLifecycleEvent,
|
|
33
|
+
dispatchPendingLifecycleEvents: () => dispatchPendingLifecycleEvents,
|
|
26
34
|
executeFieldAfterRead: () => executeFieldAfterRead,
|
|
27
35
|
executeFieldBeforeChange: () => executeFieldBeforeChange,
|
|
28
36
|
generateAIPrompt: () => generateAIPrompt,
|
|
29
37
|
generateFreshSetupPrompt: () => generateFreshSetupPrompt,
|
|
38
|
+
initializeWorkflowDocument: () => initializeWorkflowDocument,
|
|
39
|
+
materializeWorkflowDocument: () => materializeWorkflowDocument,
|
|
30
40
|
normalizeConfig: () => normalizeConfig,
|
|
31
41
|
parseMongoWhere: () => parseMongoWhere,
|
|
32
42
|
parseSort: () => parseSort,
|
|
33
43
|
parseSqlWhere: () => parseSqlWhere,
|
|
34
|
-
|
|
44
|
+
publishingWorkflow: () => publishingWorkflow,
|
|
45
|
+
runCollectionHooks: () => runCollectionHooks,
|
|
46
|
+
saveWorkflowDraft: () => saveWorkflowDraft,
|
|
47
|
+
transitionWorkflow: () => transitionWorkflow,
|
|
48
|
+
workflowCapabilities: () => workflowCapabilities
|
|
35
49
|
});
|
|
36
50
|
module.exports = __toCommonJS(index_exports);
|
|
37
51
|
|
|
52
|
+
// src/types/index.ts
|
|
53
|
+
var LIFECYCLE_EVENT_NAMES = [
|
|
54
|
+
"revision.created",
|
|
55
|
+
"workflow.transitioned",
|
|
56
|
+
"entry.published",
|
|
57
|
+
"entry.unpublished"
|
|
58
|
+
];
|
|
59
|
+
|
|
38
60
|
// src/utils/setup-prompt.ts
|
|
39
61
|
function buildEnvironmentSection(frameworkLabel, isSelfHosted, config) {
|
|
40
62
|
const credentialLines = isSelfHosted ? "" : `- Site ID : ${config.siteId}
|
|
@@ -183,6 +205,7 @@ COLLECTION OPTIONS:
|
|
|
183
205
|
- upload: true \u2014 media library with file upload support
|
|
184
206
|
- auth: true \u2014 adds login/me endpoints; password field is auto-managed
|
|
185
207
|
- audit: true \u2014 enables activity logging
|
|
208
|
+
- admin.icon \u2014 valid Lucide component name for sidebar navigation (e.g. 'Newspaper')
|
|
186
209
|
- admin.useAsTitle \u2014 field used as display title in admin list view
|
|
187
210
|
- admin.group \u2014 groups collection under a sidebar heading
|
|
188
211
|
- admin.hidden \u2014 hides collection from the sidebar (internal/system use)
|
|
@@ -227,7 +250,7 @@ const media = defineCollection({
|
|
|
227
250
|
|
|
228
251
|
const pages = defineCollection({
|
|
229
252
|
slug: 'pages',
|
|
230
|
-
admin: { useAsTitle: 'title', group: 'Content' },
|
|
253
|
+
admin: { icon: 'FileText', useAsTitle: 'title', group: 'Content' },
|
|
231
254
|
fields: [
|
|
232
255
|
{ name: 'title', label: 'Title', type: 'text', required: true },
|
|
233
256
|
{ name: 'slug', label: 'URL Slug', type: 'text', required: true, unique: true },
|
|
@@ -855,6 +878,250 @@ function generateAIPrompt(activeTab, config) {
|
|
|
855
878
|
return sections.join("\n");
|
|
856
879
|
}
|
|
857
880
|
|
|
881
|
+
// src/workflows.ts
|
|
882
|
+
var WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
|
|
883
|
+
var LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
|
|
884
|
+
function publishingWorkflow() {
|
|
885
|
+
return {
|
|
886
|
+
initialState: "draft",
|
|
887
|
+
draftState: "draft",
|
|
888
|
+
states: [
|
|
889
|
+
{ name: "draft", label: "Draft", color: "neutral" },
|
|
890
|
+
{ name: "in_review", label: "In review", color: "warning" },
|
|
891
|
+
{ name: "published", label: "Published", color: "success", published: true }
|
|
892
|
+
],
|
|
893
|
+
transitions: [
|
|
894
|
+
{ name: "submit", label: "Submit for review", from: "draft", to: "in_review", requiredCapabilities: ["entry.submit"] },
|
|
895
|
+
{ name: "publish", label: "Publish", from: "in_review", to: "published", requiredCapabilities: ["entry.publish"] },
|
|
896
|
+
{ name: "reject", label: "Request changes", from: "in_review", to: "draft", requiredCapabilities: ["entry.publish"], requireComment: true },
|
|
897
|
+
{ name: "unpublish", label: "Unpublish", from: "published", to: "draft", requiredCapabilities: ["entry.unpublish"], unpublish: true }
|
|
898
|
+
],
|
|
899
|
+
roles: [
|
|
900
|
+
{ role: "editor", capabilities: ["entry.edit", "entry.submit"] },
|
|
901
|
+
{ role: "publisher", capabilities: ["entry.edit", "entry.submit", "entry.publish", "entry.unpublish"] },
|
|
902
|
+
{ role: "admin", capabilities: ["entry.edit", "entry.submit", "entry.publish", "entry.unpublish"] }
|
|
903
|
+
]
|
|
904
|
+
};
|
|
905
|
+
}
|
|
906
|
+
function publicMetadata(meta) {
|
|
907
|
+
const { availableTransitions: _availableTransitions, ...safe } = meta;
|
|
908
|
+
return safe;
|
|
909
|
+
}
|
|
910
|
+
function workflowCapabilities(workflow, user) {
|
|
911
|
+
const capabilities = new Set(Array.isArray(user?.capabilities) ? user.capabilities : []);
|
|
912
|
+
const roles = Array.isArray(user?.roles) ? user.roles : [];
|
|
913
|
+
for (const mapping of workflow.roles ?? []) {
|
|
914
|
+
if (roles.includes(mapping.role)) mapping.capabilities.forEach((capability) => capabilities.add(capability));
|
|
915
|
+
}
|
|
916
|
+
return capabilities;
|
|
917
|
+
}
|
|
918
|
+
function availableWorkflowTransitions(workflow, state, user) {
|
|
919
|
+
const capabilities = workflowCapabilities(workflow, user);
|
|
920
|
+
return workflow.transitions.filter((transition) => {
|
|
921
|
+
const from = Array.isArray(transition.from) ? transition.from : [transition.from];
|
|
922
|
+
return from.includes(state) && (transition.requiredCapabilities ?? []).every((item) => capabilities.has(item));
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
function initializeWorkflowDocument(data, workflow) {
|
|
926
|
+
return {
|
|
927
|
+
...data,
|
|
928
|
+
__workflow: { state: workflow.initialState, revision: 1 }
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
function materializeWorkflowDocument(doc, workflow, user) {
|
|
932
|
+
const meta = doc.__workflow;
|
|
933
|
+
if (!meta) return doc;
|
|
934
|
+
const { __published, __workflow, ...working } = doc;
|
|
935
|
+
if (!user) {
|
|
936
|
+
if (!__published || typeof __published !== "object") return null;
|
|
937
|
+
return { id: doc.id, ...__published, _workflow: publicMetadata(meta) };
|
|
938
|
+
}
|
|
939
|
+
return {
|
|
940
|
+
...working,
|
|
941
|
+
_workflow: {
|
|
942
|
+
...meta,
|
|
943
|
+
availableTransitions: availableWorkflowTransitions(workflow, meta.state, user).map((item) => item.name)
|
|
944
|
+
}
|
|
945
|
+
};
|
|
946
|
+
}
|
|
947
|
+
function eventId() {
|
|
948
|
+
return globalThis.crypto?.randomUUID?.() ?? `evt_${Date.now()}_${Math.random().toString(36).slice(2)}`;
|
|
949
|
+
}
|
|
950
|
+
function createLifecycleEvent(args) {
|
|
951
|
+
return {
|
|
952
|
+
id: eventId(),
|
|
953
|
+
name: args.name,
|
|
954
|
+
collection: args.collection,
|
|
955
|
+
documentId: args.documentId,
|
|
956
|
+
occurredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
957
|
+
actorId: args.actorId,
|
|
958
|
+
payload: args.payload,
|
|
959
|
+
attempts: 0,
|
|
960
|
+
status: "pending"
|
|
961
|
+
};
|
|
962
|
+
}
|
|
963
|
+
async function persistEvent(db, event) {
|
|
964
|
+
await db.create({ collection: LIFECYCLE_EVENTS_COLLECTION, data: event });
|
|
965
|
+
}
|
|
966
|
+
async function dispatchLifecycleEvent(config, event) {
|
|
967
|
+
const db = config.db;
|
|
968
|
+
if (!db || !config.events?.handlers.length) return;
|
|
969
|
+
const maxAttempts = config.events.maxAttempts ?? 8;
|
|
970
|
+
const retryDelayMs = config.events.retryDelayMs ?? 1e3;
|
|
971
|
+
const attempts = event.attempts + 1;
|
|
972
|
+
try {
|
|
973
|
+
await db.update({ collection: LIFECYCLE_EVENTS_COLLECTION, id: event.id, data: { status: "processing", attempts } });
|
|
974
|
+
for (const handler of config.events.handlers) await handler({ ...event, status: "processing", attempts });
|
|
975
|
+
await db.update({
|
|
976
|
+
collection: LIFECYCLE_EVENTS_COLLECTION,
|
|
977
|
+
id: event.id,
|
|
978
|
+
data: { status: "delivered", attempts, deliveredAt: (/* @__PURE__ */ new Date()).toISOString(), lastError: null }
|
|
979
|
+
});
|
|
980
|
+
} catch (error) {
|
|
981
|
+
const exhausted = attempts >= maxAttempts;
|
|
982
|
+
await db.update({
|
|
983
|
+
collection: LIFECYCLE_EVENTS_COLLECTION,
|
|
984
|
+
id: event.id,
|
|
985
|
+
data: {
|
|
986
|
+
status: "failed",
|
|
987
|
+
attempts,
|
|
988
|
+
lastError: error instanceof Error ? error.message : String(error),
|
|
989
|
+
nextAttemptAt: exhausted ? null : new Date(Date.now() + retryDelayMs * 2 ** (attempts - 1)).toISOString()
|
|
990
|
+
}
|
|
991
|
+
});
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
async function dispatchPendingLifecycleEvents(config, limit = 50) {
|
|
995
|
+
if (!config.db || !config.events?.handlers.length) return 0;
|
|
996
|
+
const result = await config.db.find({
|
|
997
|
+
collection: LIFECYCLE_EVENTS_COLLECTION,
|
|
998
|
+
where: { status: { in: ["pending", "failed"] } },
|
|
999
|
+
sort: "occurredAt",
|
|
1000
|
+
limit
|
|
1001
|
+
});
|
|
1002
|
+
const now = Date.now();
|
|
1003
|
+
const due = result.docs.filter((doc) => !doc.nextAttemptAt || new Date(doc.nextAttemptAt).getTime() <= now);
|
|
1004
|
+
for (const event of due) await dispatchLifecycleEvent(config, event);
|
|
1005
|
+
return due.length;
|
|
1006
|
+
}
|
|
1007
|
+
async function saveWorkflowDraft(args) {
|
|
1008
|
+
const { config, collection, id, originalDoc, data, user } = args;
|
|
1009
|
+
const db = config.db;
|
|
1010
|
+
const workflow = collection.workflow;
|
|
1011
|
+
if (!db.transaction) throw new Error(`The configured database adapter does not support workflow transactions.`);
|
|
1012
|
+
const previous = originalDoc.__workflow;
|
|
1013
|
+
const event = createLifecycleEvent({
|
|
1014
|
+
name: "revision.created",
|
|
1015
|
+
collection: collection.slug,
|
|
1016
|
+
documentId: id,
|
|
1017
|
+
actorId: user?.sub,
|
|
1018
|
+
payload: { revision: previous.revision + 1, previousRevision: previous.revision }
|
|
1019
|
+
});
|
|
1020
|
+
const doc = await db.transaction(async (tx) => {
|
|
1021
|
+
const nextMeta = {
|
|
1022
|
+
...previous,
|
|
1023
|
+
state: originalDoc.__published ? workflow.draftState ?? workflow.initialState : previous.state,
|
|
1024
|
+
revision: previous.revision + 1
|
|
1025
|
+
};
|
|
1026
|
+
const updated = await tx.update({ collection: collection.slug, id, data: { ...data, __workflow: nextMeta } });
|
|
1027
|
+
await persistEvent(tx, event);
|
|
1028
|
+
return updated;
|
|
1029
|
+
});
|
|
1030
|
+
void dispatchLifecycleEvent(config, event);
|
|
1031
|
+
return { doc, event };
|
|
1032
|
+
}
|
|
1033
|
+
async function createWorkflowDocument(args) {
|
|
1034
|
+
const { config, collection, data, user } = args;
|
|
1035
|
+
const db = config.db;
|
|
1036
|
+
if (!db.transaction) throw new Error(`The configured database adapter does not support workflow transactions.`);
|
|
1037
|
+
let event;
|
|
1038
|
+
const doc = await db.transaction(async (tx) => {
|
|
1039
|
+
const created = await tx.create({ collection: collection.slug, data });
|
|
1040
|
+
event = createLifecycleEvent({
|
|
1041
|
+
name: "revision.created",
|
|
1042
|
+
collection: collection.slug,
|
|
1043
|
+
documentId: created.id,
|
|
1044
|
+
actorId: user?.sub,
|
|
1045
|
+
payload: { revision: 1, previousRevision: null }
|
|
1046
|
+
});
|
|
1047
|
+
await persistEvent(tx, event);
|
|
1048
|
+
return created;
|
|
1049
|
+
});
|
|
1050
|
+
void dispatchLifecycleEvent(config, event);
|
|
1051
|
+
return { doc, event };
|
|
1052
|
+
}
|
|
1053
|
+
async function transitionWorkflow(args) {
|
|
1054
|
+
const { config, collection, id, transitionName, expectedRevision, comment, user, req } = args;
|
|
1055
|
+
const db = config.db;
|
|
1056
|
+
const workflow = collection.workflow;
|
|
1057
|
+
if (!db.transaction) throw new Error(`The configured database adapter does not support workflow transactions.`);
|
|
1058
|
+
const original = await db.findOne({ collection: collection.slug, id });
|
|
1059
|
+
if (!original) throw Object.assign(new Error("Not Found"), { statusCode: 404 });
|
|
1060
|
+
const meta = original.__workflow;
|
|
1061
|
+
if (!meta) throw Object.assign(new Error("Entry has no workflow metadata"), { statusCode: 409 });
|
|
1062
|
+
if (expectedRevision !== void 0 && expectedRevision !== meta.revision) {
|
|
1063
|
+
throw Object.assign(new Error("This entry changed since it was loaded. Refresh before transitioning it."), { statusCode: 409 });
|
|
1064
|
+
}
|
|
1065
|
+
const transition = workflow.transitions.find((item) => item.name === transitionName);
|
|
1066
|
+
const fromStates = transition ? Array.isArray(transition.from) ? transition.from : [transition.from] : [];
|
|
1067
|
+
if (!transition || !fromStates.includes(meta.state)) {
|
|
1068
|
+
throw Object.assign(new Error(`Transition "${transitionName}" is not valid from "${meta.state}".`), { statusCode: 409 });
|
|
1069
|
+
}
|
|
1070
|
+
if (!availableWorkflowTransitions(workflow, meta.state, user).some((item) => item.name === transition.name)) {
|
|
1071
|
+
throw Object.assign(new Error(`You do not have permission to perform "${transition.label}".`), { statusCode: 403 });
|
|
1072
|
+
}
|
|
1073
|
+
if (transition.requireComment && !comment?.trim()) {
|
|
1074
|
+
throw Object.assign(new Error(`A comment is required for "${transition.label}".`), { statusCode: 400 });
|
|
1075
|
+
}
|
|
1076
|
+
const hookContext = { transition, from: meta.state, to: transition.to, doc: original, user, comment, req, db };
|
|
1077
|
+
for (const hook of workflow.hooks?.beforeTransition ?? []) await hook(hookContext);
|
|
1078
|
+
const events = [createLifecycleEvent({
|
|
1079
|
+
name: "workflow.transitioned",
|
|
1080
|
+
collection: collection.slug,
|
|
1081
|
+
documentId: id,
|
|
1082
|
+
actorId: user?.sub,
|
|
1083
|
+
payload: { transition: transition.name, from: meta.state, to: transition.to, revision: meta.revision, comment }
|
|
1084
|
+
})];
|
|
1085
|
+
const targetState = workflow.states.find((state) => state.name === transition.to);
|
|
1086
|
+
if (targetState.published) {
|
|
1087
|
+
events.push(createLifecycleEvent({ name: "entry.published", collection: collection.slug, documentId: id, actorId: user?.sub, payload: { revision: meta.revision } }));
|
|
1088
|
+
} else if (transition.unpublish) {
|
|
1089
|
+
events.push(createLifecycleEvent({ name: "entry.unpublished", collection: collection.slug, documentId: id, actorId: user?.sub, payload: { revision: meta.publishedRevision } }));
|
|
1090
|
+
}
|
|
1091
|
+
const updated = await db.transaction(async (tx) => {
|
|
1092
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
1093
|
+
const { __published: _published, __workflow: _workflow, id: _id, ...working } = original;
|
|
1094
|
+
const nextMeta = {
|
|
1095
|
+
...meta,
|
|
1096
|
+
state: transition.to,
|
|
1097
|
+
...targetState.published ? { publishedRevision: meta.revision, publishedAt: now, publishedBy: user?.sub } : {},
|
|
1098
|
+
...transition.unpublish ? { publishedRevision: void 0, publishedAt: void 0, publishedBy: void 0 } : {}
|
|
1099
|
+
};
|
|
1100
|
+
const data = { __workflow: nextMeta };
|
|
1101
|
+
if (targetState.published) data.__published = working;
|
|
1102
|
+
if (transition.unpublish) data.__published = null;
|
|
1103
|
+
const next = await tx.update({ collection: collection.slug, id, data });
|
|
1104
|
+
await tx.create({
|
|
1105
|
+
collection: WORKFLOW_HISTORY_COLLECTION,
|
|
1106
|
+
data: { collection: collection.slug, documentId: id, transition: transition.name, from: meta.state, to: transition.to, revision: meta.revision, comment: comment ?? null, actorId: user?.sub ?? null, createdAt: now }
|
|
1107
|
+
});
|
|
1108
|
+
for (const event of events) await persistEvent(tx, event);
|
|
1109
|
+
if (collection.audit) {
|
|
1110
|
+
await tx.create({ collection: "__audit", data: { collection: collection.slug, documentId: id, operation: "workflow.transition", user: user?.sub ?? null, timestamp: now, changes: JSON.stringify({ transition: transition.name, from: meta.state, to: transition.to, revision: meta.revision }) } });
|
|
1111
|
+
}
|
|
1112
|
+
return next;
|
|
1113
|
+
});
|
|
1114
|
+
for (const event of events) void dispatchLifecycleEvent(config, event);
|
|
1115
|
+
for (const hook of workflow.hooks?.afterTransition ?? []) {
|
|
1116
|
+
try {
|
|
1117
|
+
await hook({ ...hookContext, doc: updated, event: events[0] });
|
|
1118
|
+
} catch (error) {
|
|
1119
|
+
console.error("[dyrected/workflow] afterTransition hook failed:", error);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
return updated;
|
|
1123
|
+
}
|
|
1124
|
+
|
|
858
1125
|
// src/utils/config.ts
|
|
859
1126
|
var AUDIT_COLLECTION_SLUG = "__audit";
|
|
860
1127
|
var SYSTEM_FIELDS = [
|
|
@@ -896,10 +1163,47 @@ var AUDIT_COLLECTION = {
|
|
|
896
1163
|
],
|
|
897
1164
|
admin: { hidden: true }
|
|
898
1165
|
};
|
|
1166
|
+
var WORKFLOW_HISTORY_COLLECTION_CONFIG = {
|
|
1167
|
+
slug: WORKFLOW_HISTORY_COLLECTION,
|
|
1168
|
+
labels: { singular: "Workflow transition", plural: "Workflow transitions" },
|
|
1169
|
+
fields: [
|
|
1170
|
+
{ name: "collection", type: "text", required: true },
|
|
1171
|
+
{ name: "documentId", type: "text", required: true },
|
|
1172
|
+
{ name: "transition", type: "text", required: true },
|
|
1173
|
+
{ name: "from", type: "text", required: true },
|
|
1174
|
+
{ name: "to", type: "text", required: true },
|
|
1175
|
+
{ name: "revision", type: "number", required: true },
|
|
1176
|
+
{ name: "comment", type: "textarea" },
|
|
1177
|
+
{ name: "actorId", type: "text" },
|
|
1178
|
+
{ name: "createdAt", type: "date", required: true }
|
|
1179
|
+
],
|
|
1180
|
+
access: { read: ({ user }) => !!user, create: () => false, update: () => false, delete: () => false },
|
|
1181
|
+
admin: { hidden: true }
|
|
1182
|
+
};
|
|
1183
|
+
var LIFECYCLE_EVENTS_COLLECTION_CONFIG = {
|
|
1184
|
+
slug: LIFECYCLE_EVENTS_COLLECTION,
|
|
1185
|
+
labels: { singular: "Lifecycle event", plural: "Lifecycle events" },
|
|
1186
|
+
fields: [
|
|
1187
|
+
{ name: "name", type: "text", required: true },
|
|
1188
|
+
{ name: "collection", type: "text", required: true },
|
|
1189
|
+
{ name: "documentId", type: "text", required: true },
|
|
1190
|
+
{ name: "occurredAt", type: "date", required: true },
|
|
1191
|
+
{ name: "actorId", type: "text" },
|
|
1192
|
+
{ name: "payload", type: "json", required: true },
|
|
1193
|
+
{ name: "attempts", type: "number", required: true },
|
|
1194
|
+
{ name: "status", type: "select", options: ["pending", "processing", "delivered", "failed"], required: true },
|
|
1195
|
+
{ name: "nextAttemptAt", type: "date" },
|
|
1196
|
+
{ name: "deliveredAt", type: "date" },
|
|
1197
|
+
{ name: "lastError", type: "textarea" }
|
|
1198
|
+
],
|
|
1199
|
+
access: { read: ({ user }) => !!user?.roles?.includes("admin"), create: () => false, update: () => false, delete: () => false },
|
|
1200
|
+
admin: { hidden: true }
|
|
1201
|
+
};
|
|
899
1202
|
function normalizeConfig(config) {
|
|
900
1203
|
const collections = config?.collections || [];
|
|
901
1204
|
const globals = config?.globals || [];
|
|
902
1205
|
const needsAudit = collections.some((col) => col.audit);
|
|
1206
|
+
const needsWorkflow = collections.some((col) => col.workflow);
|
|
903
1207
|
const normalizedCollections = collections.map((col) => {
|
|
904
1208
|
let fields = col.fields || [];
|
|
905
1209
|
const existingFieldNames = new Set(fields.map((f) => f.name));
|
|
@@ -994,9 +1298,17 @@ function normalizeConfig(config) {
|
|
|
994
1298
|
};
|
|
995
1299
|
});
|
|
996
1300
|
const hasAuditCollection = normalizedCollections.some((col) => col.slug === AUDIT_COLLECTION_SLUG);
|
|
1301
|
+
const systemCollections = [];
|
|
1302
|
+
if (needsAudit && !hasAuditCollection) systemCollections.push(AUDIT_COLLECTION);
|
|
1303
|
+
if (needsWorkflow && !normalizedCollections.some((col) => col.slug === WORKFLOW_HISTORY_COLLECTION)) {
|
|
1304
|
+
systemCollections.push(WORKFLOW_HISTORY_COLLECTION_CONFIG);
|
|
1305
|
+
}
|
|
1306
|
+
if (needsWorkflow && !normalizedCollections.some((col) => col.slug === LIFECYCLE_EVENTS_COLLECTION)) {
|
|
1307
|
+
systemCollections.push(LIFECYCLE_EVENTS_COLLECTION_CONFIG);
|
|
1308
|
+
}
|
|
997
1309
|
return {
|
|
998
1310
|
...config,
|
|
999
|
-
collections: [...normalizedCollections, ...
|
|
1311
|
+
collections: [...normalizedCollections, ...systemCollections],
|
|
1000
1312
|
globals
|
|
1001
1313
|
};
|
|
1002
1314
|
}
|
|
@@ -1347,16 +1659,30 @@ function defineConfig(config) {
|
|
|
1347
1659
|
}
|
|
1348
1660
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1349
1661
|
0 && (module.exports = {
|
|
1662
|
+
LIFECYCLE_EVENTS_COLLECTION,
|
|
1663
|
+
LIFECYCLE_EVENT_NAMES,
|
|
1664
|
+
WORKFLOW_HISTORY_COLLECTION,
|
|
1665
|
+
availableWorkflowTransitions,
|
|
1666
|
+
createLifecycleEvent,
|
|
1667
|
+
createWorkflowDocument,
|
|
1350
1668
|
defineCollection,
|
|
1351
1669
|
defineConfig,
|
|
1352
1670
|
defineGlobal,
|
|
1671
|
+
dispatchLifecycleEvent,
|
|
1672
|
+
dispatchPendingLifecycleEvents,
|
|
1353
1673
|
executeFieldAfterRead,
|
|
1354
1674
|
executeFieldBeforeChange,
|
|
1355
1675
|
generateAIPrompt,
|
|
1356
1676
|
generateFreshSetupPrompt,
|
|
1677
|
+
initializeWorkflowDocument,
|
|
1678
|
+
materializeWorkflowDocument,
|
|
1357
1679
|
normalizeConfig,
|
|
1358
1680
|
parseMongoWhere,
|
|
1359
1681
|
parseSort,
|
|
1360
1682
|
parseSqlWhere,
|
|
1361
|
-
|
|
1683
|
+
publishingWorkflow,
|
|
1684
|
+
runCollectionHooks,
|
|
1685
|
+
saveWorkflowDraft,
|
|
1686
|
+
transitionWorkflow,
|
|
1687
|
+
workflowCapabilities
|
|
1362
1688
|
});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields,
|
|
2
|
-
export {
|
|
1
|
+
import { D as DyrectedConfig, F as Field, W as WorkflowConfig, A as AuthenticatedUser, a as WorkflowTransition, L as LifecycleEventName, b as LifecycleEvent, C as CollectionConfig, B as BaseDocument, H as HookRequestContext, P as Prettify, I as InferDocShape, S as SystemDocFields, c as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './index-DTrpTru7.cjs';
|
|
2
|
+
export { d as AccessFunction, e as AdminConfig, f as AdminDashboardComponentSlots, g as AdminIconName, h as Block, i as CollectionAfterChangeHook, j as CollectionAfterDeleteHook, k as CollectionAfterReadHook, l as CollectionAfterTransitionHook, m as CollectionBeforeChangeHook, n as CollectionBeforeDeleteHook, o as CollectionBeforeReadHook, p as CollectionBeforeTransitionHook, q as CollectionListComponentSlots, r as DatabaseAdapter, s as DynamicOptionItem, t as DynamicOptionsConfig, u as DynamicOptionsResolver, v as DynamicOptionsResolverArgs, w as FieldAfterReadHook, x as FieldBeforeChangeHook, y as FieldHook, z as FieldType, E as FileData, J as GlobalAfterChangeHook, K as GlobalAfterReadHook, M as GlobalBeforeChangeHook, N as GlobalBeforeReadHook, O as HookFunction, Q as ImageService, R as LIFECYCLE_EVENT_NAMES, T as LifecycleEventHandler, V as PaginatedResult, X as ReadonlyDatabaseAdapter, Y as StorageAdapter, Z as UploadConfig, _ as WorkflowMetadata, $ as WorkflowRole, a0 as WorkflowState, a1 as WorkflowTransitionContext } from './index-DTrpTru7.cjs';
|
|
3
|
+
import 'lucide-react';
|
|
3
4
|
|
|
4
5
|
interface SetupPromptConfig {
|
|
5
6
|
siteName?: string;
|
|
@@ -128,6 +129,58 @@ declare function executeFieldBeforeChange(fields: Field[], data: Record<string,
|
|
|
128
129
|
*/
|
|
129
130
|
declare function executeFieldAfterRead(fields: Field[], doc: Record<string, unknown>, user: unknown, db?: unknown): Promise<Record<string, unknown>>;
|
|
130
131
|
|
|
132
|
+
declare const WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
|
|
133
|
+
declare const LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
|
|
134
|
+
declare function publishingWorkflow(): WorkflowConfig;
|
|
135
|
+
declare function workflowCapabilities(workflow: WorkflowConfig, user?: AuthenticatedUser): Set<string>;
|
|
136
|
+
declare function availableWorkflowTransitions(workflow: WorkflowConfig, state: string, user?: AuthenticatedUser): WorkflowTransition[];
|
|
137
|
+
declare function initializeWorkflowDocument(data: Record<string, unknown>, workflow: WorkflowConfig): {
|
|
138
|
+
__workflow: {
|
|
139
|
+
state: string;
|
|
140
|
+
revision: number;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
declare function materializeWorkflowDocument(doc: BaseDocument, workflow: WorkflowConfig, user?: AuthenticatedUser): BaseDocument | null;
|
|
144
|
+
declare function createLifecycleEvent(args: {
|
|
145
|
+
name: LifecycleEventName;
|
|
146
|
+
collection: string;
|
|
147
|
+
documentId: string;
|
|
148
|
+
actorId?: string;
|
|
149
|
+
payload: Record<string, unknown>;
|
|
150
|
+
}): LifecycleEvent;
|
|
151
|
+
declare function dispatchLifecycleEvent(config: DyrectedConfig, event: LifecycleEvent): Promise<void>;
|
|
152
|
+
declare function dispatchPendingLifecycleEvents(config: DyrectedConfig, limit?: number): Promise<number>;
|
|
153
|
+
declare function saveWorkflowDraft(args: {
|
|
154
|
+
config: DyrectedConfig;
|
|
155
|
+
collection: CollectionConfig;
|
|
156
|
+
id: string;
|
|
157
|
+
originalDoc: BaseDocument;
|
|
158
|
+
data: Record<string, unknown>;
|
|
159
|
+
user?: AuthenticatedUser;
|
|
160
|
+
}): Promise<{
|
|
161
|
+
doc: BaseDocument;
|
|
162
|
+
event: LifecycleEvent;
|
|
163
|
+
}>;
|
|
164
|
+
declare function createWorkflowDocument(args: {
|
|
165
|
+
config: DyrectedConfig;
|
|
166
|
+
collection: CollectionConfig;
|
|
167
|
+
data: Record<string, unknown>;
|
|
168
|
+
user?: AuthenticatedUser;
|
|
169
|
+
}): Promise<{
|
|
170
|
+
doc: BaseDocument;
|
|
171
|
+
event: LifecycleEvent;
|
|
172
|
+
}>;
|
|
173
|
+
declare function transitionWorkflow(args: {
|
|
174
|
+
config: DyrectedConfig;
|
|
175
|
+
collection: CollectionConfig;
|
|
176
|
+
id: string;
|
|
177
|
+
transitionName: string;
|
|
178
|
+
expectedRevision?: number;
|
|
179
|
+
comment?: string;
|
|
180
|
+
user?: AuthenticatedUser;
|
|
181
|
+
req: HookRequestContext;
|
|
182
|
+
}): Promise<BaseDocument>;
|
|
183
|
+
|
|
131
184
|
/**
|
|
132
185
|
* Define a collection. When called without an explicit type argument, TypeScript
|
|
133
186
|
* automatically infers the document shape from the `fields` array you provide —
|
|
@@ -219,4 +272,4 @@ declare function defineGlobal<TDoc extends object>(config: GlobalConfig<TDoc>):
|
|
|
219
272
|
*/
|
|
220
273
|
declare function defineConfig(config: DyrectedConfig): DyrectedConfig;
|
|
221
274
|
|
|
222
|
-
export { AuthDocFields, CollectionConfig, DyrectedConfig, Field, GlobalConfig, InferDocShape, Prettify, type SetupPromptConfig, type SortClause, type SortDirection, type SqlWhereResult, SystemDocFields, UploadDocFields, type WhereClause, type WhereOperator, type WhereOperatorName, defineCollection, defineConfig, defineGlobal, executeFieldAfterRead, executeFieldBeforeChange, generateAIPrompt, generateFreshSetupPrompt, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, runCollectionHooks };
|
|
275
|
+
export { AuthDocFields, AuthenticatedUser, BaseDocument, CollectionConfig, DyrectedConfig, Field, GlobalConfig, HookRequestContext, InferDocShape, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, Prettify, type SetupPromptConfig, type SortClause, type SortDirection, type SqlWhereResult, SystemDocFields, UploadDocFields, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, createLifecycleEvent, createWorkflowDocument, defineCollection, defineConfig, defineGlobal, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateAIPrompt, generateFreshSetupPrompt, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, runCollectionHooks, saveWorkflowDraft, transitionWorkflow, workflowCapabilities };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { D as DyrectedConfig, F as Field, C as CollectionConfig, P as Prettify, I as InferDocShape, S as SystemDocFields,
|
|
2
|
-
export {
|
|
1
|
+
import { D as DyrectedConfig, F as Field, W as WorkflowConfig, A as AuthenticatedUser, a as WorkflowTransition, L as LifecycleEventName, b as LifecycleEvent, C as CollectionConfig, B as BaseDocument, H as HookRequestContext, P as Prettify, I as InferDocShape, S as SystemDocFields, c as AuthDocFields, U as UploadDocFields, G as GlobalConfig } from './index-DTrpTru7.js';
|
|
2
|
+
export { d as AccessFunction, e as AdminConfig, f as AdminDashboardComponentSlots, g as AdminIconName, h as Block, i as CollectionAfterChangeHook, j as CollectionAfterDeleteHook, k as CollectionAfterReadHook, l as CollectionAfterTransitionHook, m as CollectionBeforeChangeHook, n as CollectionBeforeDeleteHook, o as CollectionBeforeReadHook, p as CollectionBeforeTransitionHook, q as CollectionListComponentSlots, r as DatabaseAdapter, s as DynamicOptionItem, t as DynamicOptionsConfig, u as DynamicOptionsResolver, v as DynamicOptionsResolverArgs, w as FieldAfterReadHook, x as FieldBeforeChangeHook, y as FieldHook, z as FieldType, E as FileData, J as GlobalAfterChangeHook, K as GlobalAfterReadHook, M as GlobalBeforeChangeHook, N as GlobalBeforeReadHook, O as HookFunction, Q as ImageService, R as LIFECYCLE_EVENT_NAMES, T as LifecycleEventHandler, V as PaginatedResult, X as ReadonlyDatabaseAdapter, Y as StorageAdapter, Z as UploadConfig, _ as WorkflowMetadata, $ as WorkflowRole, a0 as WorkflowState, a1 as WorkflowTransitionContext } from './index-DTrpTru7.js';
|
|
3
|
+
import 'lucide-react';
|
|
3
4
|
|
|
4
5
|
interface SetupPromptConfig {
|
|
5
6
|
siteName?: string;
|
|
@@ -128,6 +129,58 @@ declare function executeFieldBeforeChange(fields: Field[], data: Record<string,
|
|
|
128
129
|
*/
|
|
129
130
|
declare function executeFieldAfterRead(fields: Field[], doc: Record<string, unknown>, user: unknown, db?: unknown): Promise<Record<string, unknown>>;
|
|
130
131
|
|
|
132
|
+
declare const WORKFLOW_HISTORY_COLLECTION = "__workflow_history";
|
|
133
|
+
declare const LIFECYCLE_EVENTS_COLLECTION = "__lifecycle_events";
|
|
134
|
+
declare function publishingWorkflow(): WorkflowConfig;
|
|
135
|
+
declare function workflowCapabilities(workflow: WorkflowConfig, user?: AuthenticatedUser): Set<string>;
|
|
136
|
+
declare function availableWorkflowTransitions(workflow: WorkflowConfig, state: string, user?: AuthenticatedUser): WorkflowTransition[];
|
|
137
|
+
declare function initializeWorkflowDocument(data: Record<string, unknown>, workflow: WorkflowConfig): {
|
|
138
|
+
__workflow: {
|
|
139
|
+
state: string;
|
|
140
|
+
revision: number;
|
|
141
|
+
};
|
|
142
|
+
};
|
|
143
|
+
declare function materializeWorkflowDocument(doc: BaseDocument, workflow: WorkflowConfig, user?: AuthenticatedUser): BaseDocument | null;
|
|
144
|
+
declare function createLifecycleEvent(args: {
|
|
145
|
+
name: LifecycleEventName;
|
|
146
|
+
collection: string;
|
|
147
|
+
documentId: string;
|
|
148
|
+
actorId?: string;
|
|
149
|
+
payload: Record<string, unknown>;
|
|
150
|
+
}): LifecycleEvent;
|
|
151
|
+
declare function dispatchLifecycleEvent(config: DyrectedConfig, event: LifecycleEvent): Promise<void>;
|
|
152
|
+
declare function dispatchPendingLifecycleEvents(config: DyrectedConfig, limit?: number): Promise<number>;
|
|
153
|
+
declare function saveWorkflowDraft(args: {
|
|
154
|
+
config: DyrectedConfig;
|
|
155
|
+
collection: CollectionConfig;
|
|
156
|
+
id: string;
|
|
157
|
+
originalDoc: BaseDocument;
|
|
158
|
+
data: Record<string, unknown>;
|
|
159
|
+
user?: AuthenticatedUser;
|
|
160
|
+
}): Promise<{
|
|
161
|
+
doc: BaseDocument;
|
|
162
|
+
event: LifecycleEvent;
|
|
163
|
+
}>;
|
|
164
|
+
declare function createWorkflowDocument(args: {
|
|
165
|
+
config: DyrectedConfig;
|
|
166
|
+
collection: CollectionConfig;
|
|
167
|
+
data: Record<string, unknown>;
|
|
168
|
+
user?: AuthenticatedUser;
|
|
169
|
+
}): Promise<{
|
|
170
|
+
doc: BaseDocument;
|
|
171
|
+
event: LifecycleEvent;
|
|
172
|
+
}>;
|
|
173
|
+
declare function transitionWorkflow(args: {
|
|
174
|
+
config: DyrectedConfig;
|
|
175
|
+
collection: CollectionConfig;
|
|
176
|
+
id: string;
|
|
177
|
+
transitionName: string;
|
|
178
|
+
expectedRevision?: number;
|
|
179
|
+
comment?: string;
|
|
180
|
+
user?: AuthenticatedUser;
|
|
181
|
+
req: HookRequestContext;
|
|
182
|
+
}): Promise<BaseDocument>;
|
|
183
|
+
|
|
131
184
|
/**
|
|
132
185
|
* Define a collection. When called without an explicit type argument, TypeScript
|
|
133
186
|
* automatically infers the document shape from the `fields` array you provide —
|
|
@@ -219,4 +272,4 @@ declare function defineGlobal<TDoc extends object>(config: GlobalConfig<TDoc>):
|
|
|
219
272
|
*/
|
|
220
273
|
declare function defineConfig(config: DyrectedConfig): DyrectedConfig;
|
|
221
274
|
|
|
222
|
-
export { AuthDocFields, CollectionConfig, DyrectedConfig, Field, GlobalConfig, InferDocShape, Prettify, type SetupPromptConfig, type SortClause, type SortDirection, type SqlWhereResult, SystemDocFields, UploadDocFields, type WhereClause, type WhereOperator, type WhereOperatorName, defineCollection, defineConfig, defineGlobal, executeFieldAfterRead, executeFieldBeforeChange, generateAIPrompt, generateFreshSetupPrompt, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, runCollectionHooks };
|
|
275
|
+
export { AuthDocFields, AuthenticatedUser, BaseDocument, CollectionConfig, DyrectedConfig, Field, GlobalConfig, HookRequestContext, InferDocShape, LIFECYCLE_EVENTS_COLLECTION, LifecycleEvent, LifecycleEventName, Prettify, type SetupPromptConfig, type SortClause, type SortDirection, type SqlWhereResult, SystemDocFields, UploadDocFields, WORKFLOW_HISTORY_COLLECTION, type WhereClause, type WhereOperator, type WhereOperatorName, WorkflowConfig, WorkflowTransition, availableWorkflowTransitions, createLifecycleEvent, createWorkflowDocument, defineCollection, defineConfig, defineGlobal, dispatchLifecycleEvent, dispatchPendingLifecycleEvents, executeFieldAfterRead, executeFieldBeforeChange, generateAIPrompt, generateFreshSetupPrompt, initializeWorkflowDocument, materializeWorkflowDocument, normalizeConfig, parseMongoWhere, parseSort, parseSqlWhere, publishingWorkflow, runCollectionHooks, saveWorkflowDraft, transitionWorkflow, workflowCapabilities };
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import {
|
|
2
|
+
LIFECYCLE_EVENTS_COLLECTION,
|
|
3
|
+
WORKFLOW_HISTORY_COLLECTION,
|
|
4
|
+
availableWorkflowTransitions,
|
|
5
|
+
createLifecycleEvent,
|
|
6
|
+
createWorkflowDocument,
|
|
7
|
+
dispatchLifecycleEvent,
|
|
8
|
+
dispatchPendingLifecycleEvents,
|
|
2
9
|
executeFieldAfterRead,
|
|
3
10
|
executeFieldBeforeChange,
|
|
11
|
+
initializeWorkflowDocument,
|
|
12
|
+
materializeWorkflowDocument,
|
|
4
13
|
normalizeConfig,
|
|
5
|
-
|
|
6
|
-
|
|
14
|
+
publishingWorkflow,
|
|
15
|
+
runCollectionHooks,
|
|
16
|
+
saveWorkflowDraft,
|
|
17
|
+
transitionWorkflow,
|
|
18
|
+
workflowCapabilities
|
|
19
|
+
} from "./chunk-CQDVPMEU.js";
|
|
20
|
+
|
|
21
|
+
// src/types/index.ts
|
|
22
|
+
var LIFECYCLE_EVENT_NAMES = [
|
|
23
|
+
"revision.created",
|
|
24
|
+
"workflow.transitioned",
|
|
25
|
+
"entry.published",
|
|
26
|
+
"entry.unpublished"
|
|
27
|
+
];
|
|
7
28
|
|
|
8
29
|
// src/utils/setup-prompt.ts
|
|
9
30
|
function buildEnvironmentSection(frameworkLabel, isSelfHosted, config) {
|
|
@@ -153,6 +174,7 @@ COLLECTION OPTIONS:
|
|
|
153
174
|
- upload: true \u2014 media library with file upload support
|
|
154
175
|
- auth: true \u2014 adds login/me endpoints; password field is auto-managed
|
|
155
176
|
- audit: true \u2014 enables activity logging
|
|
177
|
+
- admin.icon \u2014 valid Lucide component name for sidebar navigation (e.g. 'Newspaper')
|
|
156
178
|
- admin.useAsTitle \u2014 field used as display title in admin list view
|
|
157
179
|
- admin.group \u2014 groups collection under a sidebar heading
|
|
158
180
|
- admin.hidden \u2014 hides collection from the sidebar (internal/system use)
|
|
@@ -197,7 +219,7 @@ const media = defineCollection({
|
|
|
197
219
|
|
|
198
220
|
const pages = defineCollection({
|
|
199
221
|
slug: 'pages',
|
|
200
|
-
admin: { useAsTitle: 'title', group: 'Content' },
|
|
222
|
+
admin: { icon: 'FileText', useAsTitle: 'title', group: 'Content' },
|
|
201
223
|
fields: [
|
|
202
224
|
{ name: 'title', label: 'Title', type: 'text', required: true },
|
|
203
225
|
{ name: 'slug', label: 'URL Slug', type: 'text', required: true, unique: true },
|
|
@@ -1011,16 +1033,30 @@ function defineConfig(config) {
|
|
|
1011
1033
|
return config;
|
|
1012
1034
|
}
|
|
1013
1035
|
export {
|
|
1036
|
+
LIFECYCLE_EVENTS_COLLECTION,
|
|
1037
|
+
LIFECYCLE_EVENT_NAMES,
|
|
1038
|
+
WORKFLOW_HISTORY_COLLECTION,
|
|
1039
|
+
availableWorkflowTransitions,
|
|
1040
|
+
createLifecycleEvent,
|
|
1041
|
+
createWorkflowDocument,
|
|
1014
1042
|
defineCollection,
|
|
1015
1043
|
defineConfig,
|
|
1016
1044
|
defineGlobal,
|
|
1045
|
+
dispatchLifecycleEvent,
|
|
1046
|
+
dispatchPendingLifecycleEvents,
|
|
1017
1047
|
executeFieldAfterRead,
|
|
1018
1048
|
executeFieldBeforeChange,
|
|
1019
1049
|
generateAIPrompt,
|
|
1020
1050
|
generateFreshSetupPrompt,
|
|
1051
|
+
initializeWorkflowDocument,
|
|
1052
|
+
materializeWorkflowDocument,
|
|
1021
1053
|
normalizeConfig,
|
|
1022
1054
|
parseMongoWhere,
|
|
1023
1055
|
parseSort,
|
|
1024
1056
|
parseSqlWhere,
|
|
1025
|
-
|
|
1057
|
+
publishingWorkflow,
|
|
1058
|
+
runCollectionHooks,
|
|
1059
|
+
saveWorkflowDraft,
|
|
1060
|
+
transitionWorkflow,
|
|
1061
|
+
workflowCapabilities
|
|
1026
1062
|
};
|