@haiiro/docuflow 0.0.16 → 0.0.17

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.
Files changed (28) hide show
  1. package/README.md +8 -2
  2. package/manifest.json +34 -19
  3. package/package.json +1 -1
  4. package/public/app/docflow-app.js +5 -5
  5. package/src/front-components/docflow-documents.front-component.mjs +1 -1
  6. package/src/front-components/docflow-processes.front-component.mjs +35 -35
  7. package/src/front-components/docflow-processes.front-component.tsx +187 -85
  8. package/src/front-components/docflow-tasks.front-component.mjs +24 -24
  9. package/src/front-components/launch-process.front-component.mjs +19 -19
  10. package/src/front-components/launch-process.front-component.tsx +36 -60
  11. package/src/front-components/process-steps.front-component.mjs +17 -17
  12. package/src/front-components/task-form.front-component.mjs +10 -10
  13. package/src/logic-functions/bitrix-app.logic-function.mjs +1 -1
  14. package/src/logic-functions/complete-task.logic-function.mjs +39 -8
  15. package/src/logic-functions/docflow-app.logic-function.mjs +1 -1
  16. package/src/logic-functions/hand-out-form-step.logic-function.mjs +71278 -11217
  17. package/src/logic-functions/hand-out-form-step.logic-function.ts +1 -1
  18. package/src/logic-functions/launch-process.logic-function.mjs +269 -33
  19. package/src/logic-functions/launch-process.logic-function.ts +42 -37
  20. package/src/logic-functions/on-task-updated.logic-function.mjs +39 -8
  21. package/src/logic-functions/on-workflow-run-updated.logic-function.mjs +35 -9
  22. package/src/logic-functions/on-workflow-run-updated.logic-function.ts +6 -3
  23. package/src/logic-functions/process-catalog.logic-function.mjs +119726 -0
  24. package/src/logic-functions/process-catalog.logic-function.ts +84 -0
  25. package/src/logic-functions/publish-process.logic-function.mjs +218 -16
  26. package/src/logic-functions/publish-process.logic-function.ts +13 -5
  27. package/src/logic-functions/save-launch-fields.logic-function.mjs +5 -2
  28. package/src/logic-functions/save-step-settings.logic-function.mjs +5 -2
@@ -59485,12 +59485,16 @@ var readUserMessage = (value) => {
59485
59485
  }
59486
59486
  return void 0;
59487
59487
  };
59488
+ var isMissingGraphqlField = (error) => error instanceof CoreGraphqlError && /Cannot query field|Unknown type/i.test(error.message);
59488
59489
  var callCoreGraphql = async ({
59489
59490
  query,
59490
- variables
59491
+ variables,
59492
+ runAs = "person"
59491
59493
  }) => {
59492
59494
  const apiUrl = process.env.TWENTY_API_URL;
59493
- const token = process.env.TWENTY_APP_ACCESS_TOKEN;
59495
+ const personToken = process.env.TWENTY_APP_ACCESS_TOKEN;
59496
+ const applicationToken = process.env.TWENTY_APP_APPLICATION_ACCESS_TOKEN;
59497
+ const token = runAs === "person" ? personToken ?? applicationToken : applicationToken ?? personToken;
59494
59498
  if (apiUrl === void 0 || token === void 0) {
59495
59499
  throw new CoreGraphqlError(
59496
59500
  "TWENTY_API_URL or TWENTY_APP_ACCESS_TOKEN is not set",
@@ -59515,6 +59519,9 @@ var callCoreGraphql = async ({
59515
59519
  }
59516
59520
  return body.data;
59517
59521
  };
59522
+ var SUBMIT_FORM_STEP_MUTATION = `mutation SubmitFormStep($input: SubmitFormStepInput!) {
59523
+ submitFormStep(input: $input)
59524
+ }`;
59518
59525
  var ANSWER_TOOL_CALL_MUTATION = `mutation AnswerToolCall($input: AnswerToolCallInput!) {
59519
59526
  answerToolCall(input: $input) { streamId }
59520
59527
  }`;
@@ -59574,17 +59581,24 @@ var getFormStepAssignment = ({
59574
59581
  now
59575
59582
  )
59576
59583
  });
59584
+ var getStepWaitKey = ({
59585
+ workflowRunId,
59586
+ stepId,
59587
+ stepInfo
59588
+ }) => typeof stepInfo?.threadId === "string" && stepInfo.threadId.length > 0 ? stepInfo.threadId : `${workflowRunId}.${stepId}`;
59589
+ var isStepWaitingForAnswer = (stepInfo) => stepInfo?.status === "PENDING" && (stepInfo.error === void 0 || stepInfo.error === null) && (typeof stepInfo.threadId === "string" && stepInfo.threadId.length > 0 || stepInfo.wait?.type === "CALLBACK");
59577
59590
 
59578
59591
  // src/server/workflow-engine.ts
59579
59592
  var answerFormStep = async ({
59580
59593
  state,
59594
+ workflowRunId,
59581
59595
  stepId,
59582
- threadId,
59596
+ waitKey,
59583
59597
  values
59584
59598
  }) => {
59585
59599
  const step = state?.flow?.steps?.find((candidate) => candidate.id === stepId);
59586
59600
  const stepInfo = state?.stepInfos?.[stepId];
59587
- if (step === void 0 || !isFormStep(step) || stepInfo?.status !== "PENDING" || stepInfo.threadId !== threadId) {
59601
+ if (step === void 0 || !isFormStep(step) || !isStepWaitingForAnswer(stepInfo) || getStepWaitKey({ workflowRunId, stepId, stepInfo }) !== waitKey) {
59588
59602
  return { status: "NOT_WAITING" };
59589
59603
  }
59590
59604
  const fields = resolveFormStepFields(
@@ -59608,10 +59622,26 @@ var answerFormStep = async ({
59608
59622
  ),
59609
59623
  values
59610
59624
  });
59611
- await callCoreGraphql({
59612
- query: ANSWER_TOOL_CALL_MUTATION,
59613
- variables: { input: { threadId, toolCallId: stepId, response } }
59625
+ const threadId = stepInfo?.threadId;
59626
+ const submitFormStep = () => callCoreGraphql({
59627
+ query: SUBMIT_FORM_STEP_MUTATION,
59628
+ variables: { input: { stepId, workflowRunId, response } }
59614
59629
  });
59630
+ if (typeof threadId === "string" && threadId.length > 0) {
59631
+ try {
59632
+ await callCoreGraphql({
59633
+ query: ANSWER_TOOL_CALL_MUTATION,
59634
+ variables: { input: { threadId, toolCallId: stepId, response } }
59635
+ });
59636
+ } catch (error) {
59637
+ if (!isMissingGraphqlField(error)) {
59638
+ throw error;
59639
+ }
59640
+ await submitFormStep();
59641
+ }
59642
+ } else {
59643
+ await submitFormStep();
59644
+ }
59615
59645
  return { status: "ANSWERED" };
59616
59646
  };
59617
59647
 
@@ -59625,8 +59655,9 @@ var answerStepOfTask = async (task, values) => {
59625
59655
  try {
59626
59656
  const result = await answerFormStep({
59627
59657
  state: run?.state,
59658
+ workflowRunId: task.smbWorkflowRunId,
59628
59659
  stepId: task.smbWorkflowStepId,
59629
- threadId: task.smbWorkflowThreadId,
59660
+ waitKey: task.smbWorkflowThreadId,
59630
59661
  values
59631
59662
  });
59632
59663
  return result.status === "MISSING_REQUIRED" ? { status: "MISSING_REQUIRED", labels: result.labels } : void 0;
@@ -119324,10 +119324,11 @@ var isAppEngine = (value) => getDocflowEngine(value) === "APP";
119324
119324
  // src/shared/docflow.constants.ts
119325
119325
  var DOCFLOW_LAUNCH_PARAMETERS_KEY = "smbDocflowParameters";
119326
119326
  var LAUNCH_PARAMETERS_STEP_INPUT = `{{trigger.${DOCFLOW_LAUNCH_PARAMETERS_KEY}}}`;
119327
- var LAUNCH_TRIGGER_NAME = "\u0417\u0430\u043F\u0443\u0441\u043A \u0441 \u043F\u0430\u0440\u0430\u043C\u0435\u0442\u0440\u0430\u043C\u0438";
119327
+ var DOCFLOW_LAUNCHED_BY_KEY = "smbDocflowLaunchedBy";
119328
119328
  var TASK_DONE_STATUS = "DONE";
119329
119329
  var FORM_FIELD_ROLE_SETTING = "smbRole";
119330
119330
  var FORM_FIELD_DUE_IN_DAYS_SETTING = "smbDueInDays";
119331
+ var TRIGGER_STEP_ID = "trigger";
119331
119332
 
119332
119333
  // src/shared/form/form-fields.util.ts
119333
119334
  var getFormFieldRole = (field) => {
@@ -119340,8 +119341,7 @@ var parseFormFields = (value) => Array.isArray(value) ? value.filter(
119340
119341
  ) : [];
119341
119342
 
119342
119343
  // src/shared/workflow/launch-step.util.ts
119343
- var isLaunchTrigger = (trigger) => trigger?.type === "WEBHOOK" && trigger.name === LAUNCH_TRIGGER_NAME;
119344
- var isLaunchableTrigger = (trigger) => trigger?.type === "MANUAL" || isLaunchTrigger(trigger);
119344
+ var isLaunchableTrigger = (trigger) => trigger?.type === "MANUAL" || trigger?.type === "WEBHOOK";
119345
119345
 
119346
119346
  // src/shared/workflow/workflow-run.util.ts
119347
119347
  var DAY_IN_MS = 24 * 60 * 60 * 1e3;
@@ -119398,7 +119398,26 @@ var getFormStepAssignment = ({
119398
119398
  now
119399
119399
  )
119400
119400
  });
119401
+ var getStepWaitKey = ({
119402
+ workflowRunId,
119403
+ stepId,
119404
+ stepInfo
119405
+ }) => typeof stepInfo?.threadId === "string" && stepInfo.threadId.length > 0 ? stepInfo.threadId : `${workflowRunId}.${stepId}`;
119406
+ var isStepWaitingForAnswer = (stepInfo) => stepInfo?.status === "PENDING" && (stepInfo.error === void 0 || stepInfo.error === null) && (typeof stepInfo.threadId === "string" && stepInfo.threadId.length > 0 || stepInfo.wait?.type === "CALLBACK");
119407
+ var getRunStarterWorkspaceMemberId = ({
119408
+ createdByWorkspaceMemberId,
119409
+ state
119410
+ }) => {
119411
+ if (typeof createdByWorkspaceMemberId === "string" && createdByWorkspaceMemberId.length > 0) {
119412
+ return createdByWorkspaceMemberId;
119413
+ }
119414
+ const triggerResult = state?.stepInfos?.[TRIGGER_STEP_ID]?.result;
119415
+ return readWorkspaceMemberId(
119416
+ isPlainRecord(triggerResult) ? triggerResult[DOCFLOW_LAUNCHED_BY_KEY] : void 0
119417
+ );
119418
+ };
119401
119419
  var getFormStepTaskRequests = ({
119420
+ workflowRunId,
119402
119421
  state,
119403
119422
  runStarterWorkspaceMemberId,
119404
119423
  now
@@ -119406,9 +119425,13 @@ var getFormStepTaskRequests = ({
119406
119425
  const steps = state?.flow?.steps ?? [];
119407
119426
  const stepInfos = state?.stepInfos ?? {};
119408
119427
  const isStartedByHand = isLaunchableTrigger(state?.flow?.trigger);
119428
+ const runStarterId = getRunStarterWorkspaceMemberId({
119429
+ createdByWorkspaceMemberId: runStarterWorkspaceMemberId,
119430
+ state
119431
+ });
119409
119432
  return steps.flatMap((step) => {
119410
119433
  const stepInfo = stepInfos[step.id];
119411
- if (!isFormStep(step) || stepInfo?.status !== "PENDING" || stepInfo.error !== void 0 && stepInfo.error !== null || typeof stepInfo.threadId !== "string" || stepInfo.threadId.length === 0) {
119434
+ if (!isFormStep(step) || !isStepWaitingForAnswer(stepInfo)) {
119412
119435
  return [];
119413
119436
  }
119414
119437
  const fields = resolveFormStepFields(getFormStepFields(step), stepInfos);
@@ -119416,7 +119439,7 @@ var getFormStepTaskRequests = ({
119416
119439
  fields,
119417
119440
  now
119418
119441
  });
119419
- const fallbackAssigneeId = isStartedByHand ? runStarterWorkspaceMemberId ?? void 0 : void 0;
119442
+ const fallbackAssigneeId = isStartedByHand ? runStarterId : void 0;
119420
119443
  const taskAssigneeId = assigneeWorkspaceMemberId ?? fallbackAssigneeId;
119421
119444
  if (taskAssigneeId === void 0) {
119422
119445
  return [];
@@ -119424,7 +119447,7 @@ var getFormStepTaskRequests = ({
119424
119447
  return [
119425
119448
  {
119426
119449
  stepId: step.id,
119427
- threadId: stepInfo.threadId,
119450
+ waitKey: getStepWaitKey({ workflowRunId, stepId: step.id, stepInfo }),
119428
119451
  title: step.name,
119429
119452
  assigneeWorkspaceMemberId: taskAssigneeId,
119430
119453
  dueAt,
@@ -119497,7 +119520,7 @@ var closeTasksOfAnsweredSteps = async (run) => {
119497
119520
  let closedCount = 0;
119498
119521
  for (const task of tasks) {
119499
119522
  const stepInfo = typeof task.smbWorkflowStepId === "string" ? run.state?.stepInfos?.[task.smbWorkflowStepId] : void 0;
119500
- if (stepInfo?.status !== "SUCCESS" || stepInfo.threadId !== task.smbWorkflowThreadId) {
119523
+ if (typeof task.smbWorkflowStepId !== "string" || stepInfo?.status !== "SUCCESS" || getStepWaitKey({ workflowRunId: run.id, stepId: task.smbWorkflowStepId, stepInfo }) !== task.smbWorkflowThreadId) {
119501
119524
  continue;
119502
119525
  }
119503
119526
  const answer = typeof stepInfo.result === "object" && stepInfo.result !== null ? stepInfo.result : {};
@@ -119527,6 +119550,7 @@ var handler = async (event) => {
119527
119550
  return { skipped: "NOT_RUNNING" };
119528
119551
  }
119529
119552
  const requests = getFormStepTaskRequests({
119553
+ workflowRunId: run.id,
119530
119554
  state: run.state,
119531
119555
  runStarterWorkspaceMemberId: run.createdBy?.workspaceMemberId,
119532
119556
  now: /* @__PURE__ */ new Date()
@@ -119538,9 +119562,11 @@ var handler = async (event) => {
119538
119562
  payload: {
119539
119563
  workflowRunId: run.id,
119540
119564
  stepId: request.stepId,
119541
- threadId: request.threadId
119565
+ // The wait key travels as threadId: jobs queued by 0.0.16 and
119566
+ // earlier carry that name
119567
+ threadId: request.waitKey
119542
119568
  },
119543
- jobId: `hand-out-${request.threadId}`
119569
+ jobId: `hand-out-${request.waitKey}`
119544
119570
  })),
119545
119571
  retryLimit: 2
119546
119572
  });
@@ -16,7 +16,7 @@ import {
16
16
 
17
17
  // Process tasks follow the run: a FORM step the run waits on becomes a CRM
18
18
  // task, and a step answered elsewhere closes its task. Handing out is queued
19
- // under the step's thread id, so repeated run updates create one task.
19
+ // under the step's wait key, so repeated run updates create one task.
20
20
  const handler = async (
21
21
  event: DatabaseEventPayload<ObjectRecordUpdateEvent<WorkflowRunRecord>>,
22
22
  ) => {
@@ -31,6 +31,7 @@ const handler = async (
31
31
  }
32
32
 
33
33
  const requests = getFormStepTaskRequests({
34
+ workflowRunId: run.id,
34
35
  state: run.state,
35
36
  runStarterWorkspaceMemberId: run.createdBy?.workspaceMemberId,
36
37
  now: new Date(),
@@ -44,9 +45,11 @@ const handler = async (
44
45
  payload: {
45
46
  workflowRunId: run.id,
46
47
  stepId: request.stepId,
47
- threadId: request.threadId,
48
+ // The wait key travels as threadId: jobs queued by 0.0.16 and
49
+ // earlier carry that name
50
+ threadId: request.waitKey,
48
51
  },
49
- jobId: `hand-out-${request.threadId}`,
52
+ jobId: `hand-out-${request.waitKey}`,
50
53
  })),
51
54
  retryLimit: 2,
52
55
  });