@haiiro/docuflow 0.0.20 → 0.0.22

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.
@@ -3,15 +3,16 @@ import { type RoutePayload } from 'twenty-sdk/logic-function';
3
3
 
4
4
  import { CoreGraphqlError } from 'src/shared/api/core-graphql.util';
5
5
  import { listLaunchObjects } from 'src/shared/api/object-summaries';
6
- import { readRestRecord } from 'src/shared/api/rest-response.util';
7
6
  import { getFormFieldsError } from 'src/shared/form/form-fields.util';
8
7
  import {
9
8
  getLaunchFieldsError,
10
9
  parseLaunchFields,
11
10
  parseLaunchObject,
12
11
  } from 'src/shared/workflow/launch-step.util';
13
- import { syncLaunchTrigger } from 'src/server/launch-step';
12
+ import { syncLaunchTrigger } from 'src/shared/workflow/process-engine';
14
13
  import { jsonResponse, readJsonBody, withRouteErrors } from 'src/server/http-response';
14
+ import { recordsEngine } from 'src/server/launch-step';
15
+ import { canAppEditProcesses, findDocflowProcess, saveLaunchSettings } from 'src/server/process-catalog';
15
16
  import { restClient } from 'src/server/records';
16
17
  import { logDocflow, logDocflowError } from 'src/shared/log.util';
17
18
  import { SAVE_LAUNCH_FIELDS_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER } from 'src/universal-identifiers';
@@ -45,25 +46,52 @@ const handler = async (event: RoutePayload) => {
45
46
  return jsonResponse(422, { message: `Объект «${launchObjectName}» не найден` });
46
47
  }
47
48
 
48
- // Written as the person: who may not change the process gets the refusal
49
- // of the API, not a half-saved draft.
50
- const workflow = readRestRecord<{ id: string }>(
51
- await restClient('person').patch(`/rest/workflows/${workflowId}`, {
49
+ // Read as the person: who cannot see the process cannot change it
50
+ const docflowProcess = await findDocflowProcess(workflowId, 'person');
51
+
52
+ if (docflowProcess === undefined) {
53
+ return jsonResponse(404, { message: 'Процесс документооборота не найден' });
54
+ }
55
+
56
+ await saveLaunchSettings(docflowProcess.workflowId, {
57
+ fields,
58
+ launchObject: launchObject?.nameSingular ?? null,
59
+ });
60
+
61
+ const canAppEdit = await canAppEditProcesses();
62
+
63
+ // The process record keeps them too for the NorDiv server and docflow
64
+ // before 0.0.21 (Twenty 2.45; 2.50 has no record to write)
65
+ if (canAppEdit && docflowProcess.workspaceWorkflowId !== null) {
66
+ await restClient('person').patch(`/rest/workflows/${docflowProcess.workspaceWorkflowId}`, {
52
67
  smbLaunchFields: fields.length > 0 ? fields : null,
53
68
  smbLaunchObject: launchObject?.nameSingular ?? null,
54
- }),
55
- );
69
+ });
70
+ }
71
+
72
+ // On Twenty 2.50 the standalone page changes the trigger itself, with the
73
+ // person's sign-in, and only saves the settings here
74
+ if (body.syncTrigger === false) {
75
+ return { status: 'SAVED' };
76
+ }
56
77
 
57
- if (workflow === undefined) {
58
- return jsonResponse(404, { message: 'Процесс не найден' });
78
+ if (!canAppEdit || docflowProcess.workspaceWorkflowId === null) {
79
+ return jsonResponse(409, {
80
+ code: 'EDIT_ON_STANDALONE_PAGE',
81
+ message: 'Параметры сохранены. Запуск процесса в этой версии Twenty меняется на полной странице документооборота',
82
+ });
59
83
  }
60
84
 
61
85
  try {
62
- const result = await syncLaunchTrigger({ workflowId, fields, launchObject });
86
+ const result = await syncLaunchTrigger(recordsEngine, {
87
+ workflowId: docflowProcess.workspaceWorkflowId,
88
+ fields,
89
+ launchObject,
90
+ });
63
91
 
64
92
  logDocflow('launch fields: draft synced', { workflowId, result });
65
93
 
66
- if (result?.status === 'NOT_MANUAL') {
94
+ if (result.status === 'NOT_MANUAL') {
67
95
  return jsonResponse(409, {
68
96
  message: 'Параметры сохранены, но запуск процесса не изменён: он запускается не вручную',
69
97
  });
@@ -119340,33 +119340,6 @@ var withRouteErrors = (name, handler2) => async (...args) => {
119340
119340
  }
119341
119341
  };
119342
119342
 
119343
- // src/shared/api/rest-response.util.ts
119344
- var readDataValue = (response) => {
119345
- const data = response?.data;
119346
- if (typeof data !== "object" || data === null) {
119347
- return void 0;
119348
- }
119349
- return Object.values(data)[0];
119350
- };
119351
- var readRestRecord = (response) => {
119352
- const value = readDataValue(response);
119353
- return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
119354
- };
119355
-
119356
- // src/shared/docflow.constants.ts
119357
- var DOCFLOW_LAUNCH_PARAMETERS_KEY = "smbDocflowParameters";
119358
- var LAUNCH_PARAMETERS_STEP_INPUT = `{{trigger.${DOCFLOW_LAUNCH_PARAMETERS_KEY}}}`;
119359
- var FORM_FIELD_REQUIRED_SETTING = "smbIsRequired";
119360
- var FORM_FIELD_ROLE_SETTING = "smbRole";
119361
- var FORM_FIELD_DUE_IN_DAYS_SETTING = "smbDueInDays";
119362
-
119363
- // src/server/records.ts
119364
- var clients = {
119365
- person: new u2(),
119366
- application: new u2({ runAs: "application" })
119367
- };
119368
- var restClient = (runAs) => clients[runAs];
119369
-
119370
119343
  // src/shared/api/core-graphql.util.ts
119371
119344
  var CoreGraphqlError = class extends Error {
119372
119345
  constructor(message, userMessage) {
@@ -119421,6 +119394,97 @@ var callCoreGraphql = async ({
119421
119394
  var UPDATE_WORKFLOW_VERSION_STEP_MUTATION = `mutation UpdateWorkflowVersionStep($input: UpdateWorkflowVersionStepInput!) {
119422
119395
  updateWorkflowVersionStep(input: $input) { id }
119423
119396
  }`;
119397
+ var DELETE_WORKFLOW_VERSION_STEP_MUTATION = `mutation DeleteWorkflowVersionStep($input: DeleteWorkflowVersionStepInput!) {
119398
+ deleteWorkflowVersionStep(input: $input) { __typename }
119399
+ }`;
119400
+ var UPDATE_WORKFLOW_VERSION_TRIGGER_MUTATION = `mutation UpdateWorkflowVersionTrigger($input: UpdateWorkflowVersionTriggerInput!) {
119401
+ updateWorkflowVersionTrigger(input: $input) { __typename }
119402
+ }`;
119403
+ var CREATE_DRAFT_FROM_WORKFLOW_VERSION_MUTATION = `mutation CreateDraftFromWorkflowVersion($input: CreateDraftFromWorkflowVersionInput!) {
119404
+ createDraftFromWorkflowVersion(input: $input) { id }
119405
+ }`;
119406
+
119407
+ // src/shared/api/rest-response.util.ts
119408
+ var readDataValue = (response) => {
119409
+ const data = response?.data;
119410
+ if (typeof data !== "object" || data === null) {
119411
+ return void 0;
119412
+ }
119413
+ return Object.values(data)[0];
119414
+ };
119415
+ var readRestList = (response) => {
119416
+ const value = readDataValue(response);
119417
+ return {
119418
+ records: Array.isArray(value) ? value : [],
119419
+ pageInfo: response?.pageInfo ?? {},
119420
+ totalCount: response?.totalCount
119421
+ };
119422
+ };
119423
+ var readRestRecord = (response) => {
119424
+ const value = readDataValue(response);
119425
+ return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
119426
+ };
119427
+
119428
+ // src/shared/api/rest-filter.util.ts
119429
+ var UNSAFE_FILTER_CHARACTERS = /[()[\]'",]/g;
119430
+ var sanitizeFilterText = (text) => text.replace(UNSAFE_FILTER_CHARACTERS, " ").trim();
119431
+ var quote = (value) => `'${sanitizeFilterText(value)}'`;
119432
+ var restEq = (field, value) => `${field}[eq]:${quote(value)}`;
119433
+
119434
+ // src/shared/docflow.constants.ts
119435
+ var DOCFLOW_LAUNCH_PARAMETERS_KEY = "smbDocflowParameters";
119436
+ var LAUNCH_PARAMETERS_STEP_INPUT = `{{trigger.${DOCFLOW_LAUNCH_PARAMETERS_KEY}}}`;
119437
+ var FORM_FIELD_REQUIRED_SETTING = "smbIsRequired";
119438
+ var FORM_FIELD_ROLE_SETTING = "smbRole";
119439
+ var FORM_FIELD_DUE_IN_DAYS_SETTING = "smbDueInDays";
119440
+
119441
+ // src/server/records.ts
119442
+ var clients = {
119443
+ person: new u2(),
119444
+ application: new u2({ runAs: "application" })
119445
+ };
119446
+ var restClient = (runAs) => clients[runAs];
119447
+ var listWorkflowVersions = async (runAs, workflowId) => readRestList(
119448
+ await restClient(runAs).get("/rest/workflowVersions", {
119449
+ query: {
119450
+ filter: restEq("workflowId", workflowId),
119451
+ order_by: "createdAt[DescNullsLast]",
119452
+ limit: 50
119453
+ }
119454
+ })
119455
+ ).records;
119456
+
119457
+ // src/server/launch-step.ts
119458
+ var recordsEngine = {
119459
+ listVersions: (workflowId) => listWorkflowVersions("person", workflowId),
119460
+ getVersion: async (versionId) => readRestRecord(
119461
+ await restClient("person").get(`/rest/workflowVersions/${versionId}`)
119462
+ ),
119463
+ createDraft: async (workflowId, fromVersionId) => {
119464
+ await callCoreGraphql({
119465
+ query: CREATE_DRAFT_FROM_WORKFLOW_VERSION_MUTATION,
119466
+ variables: { input: { workflowId, workflowVersionIdToCopy: fromVersionId } }
119467
+ });
119468
+ },
119469
+ updateTrigger: async (versionId, trigger) => {
119470
+ await callCoreGraphql({
119471
+ query: UPDATE_WORKFLOW_VERSION_TRIGGER_MUTATION,
119472
+ variables: { input: { workflowVersionId: versionId, trigger } }
119473
+ });
119474
+ },
119475
+ updateStep: async (versionId, step) => {
119476
+ await callCoreGraphql({
119477
+ query: UPDATE_WORKFLOW_VERSION_STEP_MUTATION,
119478
+ variables: { input: { workflowVersionId: versionId, step } }
119479
+ });
119480
+ },
119481
+ deleteStep: async (versionId, stepId) => {
119482
+ await callCoreGraphql({
119483
+ query: DELETE_WORKFLOW_VERSION_STEP_MUTATION,
119484
+ variables: { input: { workflowVersionId: versionId, stepId } }
119485
+ });
119486
+ }
119487
+ };
119424
119488
 
119425
119489
  // src/shared/form/form-fields.util.ts
119426
119490
  var getFormFieldRole = (field) => {
@@ -119489,6 +119553,30 @@ var applyStepSettings = ({
119489
119553
  var DAY_IN_MS = 24 * 60 * 60 * 1e3;
119490
119554
  var isFormStep = (step) => step.type === "FORM";
119491
119555
 
119556
+ // src/shared/workflow/process-engine.ts
119557
+ var saveStepSettings = async (engine, {
119558
+ versionId,
119559
+ stepId,
119560
+ settings,
119561
+ createId
119562
+ }) => {
119563
+ const version = await engine.getVersion(versionId);
119564
+ const step = version?.steps?.find(({ id: id3 }) => id3 === stepId);
119565
+ if (version === void 0 || step === void 0 || !isFormStep(step)) {
119566
+ return "NOT_FOUND";
119567
+ }
119568
+ if (version.status !== "DRAFT") {
119569
+ return "NOT_DRAFT";
119570
+ }
119571
+ const fields = applyStepSettings({
119572
+ fields: parseFormFields(step.settings.input),
119573
+ settings,
119574
+ createId
119575
+ });
119576
+ await engine.updateStep(version.id, { ...step, settings: { ...step.settings, input: fields } });
119577
+ return "SAVED";
119578
+ };
119579
+
119492
119580
  // src/universal-identifiers.ts
119493
119581
  var SAVE_STEP_SETTINGS_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER = "13952f55-e84f-4d3a-a5a2-f3d68d78ba5e";
119494
119582
 
@@ -119511,30 +119599,18 @@ var handler = async (event) => {
119511
119599
  if (typeof body.workflowVersionId !== "string" || typeof body.stepId !== "string" || settings === void 0) {
119512
119600
  return jsonResponse(400, { message: "\u041D\u0435 \u0443\u043A\u0430\u0437\u0430\u043D \u0448\u0430\u0433 \u0438\u043B\u0438 \u043D\u0430\u0441\u0442\u0440\u043E\u0439\u043A\u0438" });
119513
119601
  }
119514
- const version = readRestRecord(
119515
- await restClient("person").get(`/rest/workflowVersions/${body.workflowVersionId}`)
119516
- );
119517
- const step = version?.steps?.find(({ id: id3 }) => id3 === body.stepId);
119518
- if (version === void 0 || step === void 0 || !isFormStep(step)) {
119602
+ const result = await saveStepSettings(recordsEngine, {
119603
+ versionId: body.workflowVersionId,
119604
+ stepId: body.stepId,
119605
+ settings,
119606
+ createId: () => crypto.randomUUID()
119607
+ });
119608
+ if (result === "NOT_FOUND") {
119519
119609
  return jsonResponse(404, { message: "\u0428\u0430\u0433 \xAB\u0427\u0435\u043B\u043E\u0432\u0435\u0447\u0435\u0441\u043A\u0438\u0439 \u0432\u0432\u043E\u0434\xBB \u043D\u0435 \u043D\u0430\u0439\u0434\u0435\u043D" });
119520
119610
  }
119521
- if (version.status !== "DRAFT") {
119611
+ if (result === "NOT_DRAFT") {
119522
119612
  return jsonResponse(409, { message: "\u041C\u0435\u043D\u044F\u0442\u044C \u043C\u043E\u0436\u043D\u043E \u0442\u043E\u043B\u044C\u043A\u043E \u0447\u0435\u0440\u043D\u043E\u0432\u0438\u043A \u043F\u0440\u043E\u0446\u0435\u0441\u0441\u0430" });
119523
119613
  }
119524
- const fields = applyStepSettings({
119525
- fields: parseFormFields(step.settings.input),
119526
- settings,
119527
- createId: () => crypto.randomUUID()
119528
- });
119529
- await callCoreGraphql({
119530
- query: UPDATE_WORKFLOW_VERSION_STEP_MUTATION,
119531
- variables: {
119532
- input: {
119533
- workflowVersionId: version.id,
119534
- step: { ...step, settings: { ...step.settings, input: fields } }
119535
- }
119536
- }
119537
- });
119538
119614
  return { status: "SAVED" };
119539
119615
  };
119540
119616
  var save_step_settings_logic_function_default = defineLogicFunction({
@@ -2,12 +2,9 @@ import { defineLogicFunction } from 'twenty-sdk/define';
2
2
  import { type RoutePayload } from 'twenty-sdk/logic-function';
3
3
 
4
4
  import { jsonResponse, readJsonBody, withRouteErrors } from 'src/server/http-response';
5
- import { restClient, type WorkflowVersionRecord } from 'src/server/records';
6
- import { callCoreGraphql, UPDATE_WORKFLOW_VERSION_STEP_MUTATION } from 'src/shared/api/core-graphql.util';
7
- import { readRestRecord } from 'src/shared/api/rest-response.util';
8
- import { applyStepSettings, type StepSettings } from 'src/shared/form/step-settings.util';
9
- import { parseFormFields } from 'src/shared/form/form-fields.util';
10
- import { isFormStep } from 'src/shared/workflow/workflow-run.util';
5
+ import { recordsEngine } from 'src/server/launch-step';
6
+ import { type StepSettings } from 'src/shared/form/step-settings.util';
7
+ import { saveStepSettings } from 'src/shared/workflow/process-engine';
11
8
  import { SAVE_STEP_SETTINGS_LOGIC_FUNCTION_UNIVERSAL_IDENTIFIER } from 'src/universal-identifiers';
12
9
 
13
10
  const readSettings = (value: unknown): StepSettings | undefined => {
@@ -44,35 +41,21 @@ const handler = async (event: RoutePayload) => {
44
41
  return jsonResponse(400, { message: 'Не указан шаг или настройки' });
45
42
  }
46
43
 
47
- const version = readRestRecord<WorkflowVersionRecord>(
48
- await restClient('person').get(`/rest/workflowVersions/${body.workflowVersionId}`),
49
- );
50
- const step = version?.steps?.find(({ id }) => id === body.stepId);
44
+ const result = await saveStepSettings(recordsEngine, {
45
+ versionId: body.workflowVersionId,
46
+ stepId: body.stepId,
47
+ settings,
48
+ createId: () => crypto.randomUUID(),
49
+ });
51
50
 
52
- if (version === undefined || step === undefined || !isFormStep(step)) {
51
+ if (result === 'NOT_FOUND') {
53
52
  return jsonResponse(404, { message: 'Шаг «Человеческий ввод» не найден' });
54
53
  }
55
54
 
56
- if (version.status !== 'DRAFT') {
55
+ if (result === 'NOT_DRAFT') {
57
56
  return jsonResponse(409, { message: 'Менять можно только черновик процесса' });
58
57
  }
59
58
 
60
- const fields = applyStepSettings({
61
- fields: parseFormFields(step.settings.input),
62
- settings,
63
- createId: () => crypto.randomUUID(),
64
- });
65
-
66
- await callCoreGraphql({
67
- query: UPDATE_WORKFLOW_VERSION_STEP_MUTATION,
68
- variables: {
69
- input: {
70
- workflowVersionId: version.id,
71
- step: { ...step, settings: { ...step.settings, input: fields } },
72
- },
73
- },
74
- });
75
-
76
59
  return { status: 'SAVED' };
77
60
  };
78
61