@rytass/bpm-core-nestjs-module 0.20.1 → 0.21.0

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 (61) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +4 -4
  3. package/package.json +2 -2
  4. package/src/lib/form/form-data-issue.d.ts +34 -0
  5. package/src/lib/form/form-data-issue.js +59 -0
  6. package/src/lib/form/form-data-issue.js.map +1 -0
  7. package/src/lib/form/form-member-value.validator.d.ts +2 -2
  8. package/src/lib/form/form-member-value.validator.js +2 -3
  9. package/src/lib/form/form-member-value.validator.js.map +1 -1
  10. package/src/lib/form/form-org-unit-value.validator.d.ts +2 -2
  11. package/src/lib/form/form-org-unit-value.validator.js +4 -1
  12. package/src/lib/form/form-org-unit-value.validator.js.map +1 -1
  13. package/src/lib/form/form-schema.validator.js +40 -0
  14. package/src/lib/form/form-schema.validator.js.map +1 -1
  15. package/src/lib/migrations/0000000031000-approval-instance-form-data-gin.d.ts +29 -0
  16. package/src/lib/migrations/0000000031000-approval-instance-form-data-gin.js +44 -0
  17. package/src/lib/migrations/0000000031000-approval-instance-form-data-gin.js.map +1 -0
  18. package/src/lib/migrations/index.d.ts +1 -0
  19. package/src/lib/migrations/index.js +3 -0
  20. package/src/lib/migrations/index.js.map +1 -1
  21. package/src/lib/template/filterable-field-guard.d.ts +49 -0
  22. package/src/lib/template/filterable-field-guard.js +141 -0
  23. package/src/lib/template/filterable-field-guard.js.map +1 -0
  24. package/src/lib/template/filterable-field-issue.object.d.ts +21 -0
  25. package/src/lib/template/filterable-field-issue.object.js +65 -0
  26. package/src/lib/template/filterable-field-issue.object.js.map +1 -0
  27. package/src/lib/template/filterable-field.queries.d.ts +20 -0
  28. package/src/lib/template/filterable-field.queries.js +80 -0
  29. package/src/lib/template/filterable-field.queries.js.map +1 -0
  30. package/src/lib/template/index.d.ts +1 -0
  31. package/src/lib/template/index.js +1 -0
  32. package/src/lib/template/index.js.map +1 -1
  33. package/src/lib/template/template.module.js +2 -0
  34. package/src/lib/template/template.module.js.map +1 -1
  35. package/src/lib/template/template.service.d.ts +39 -0
  36. package/src/lib/template/template.service.js +167 -44
  37. package/src/lib/template/template.service.js.map +1 -1
  38. package/src/lib/workflow-engine/approval-instance-field-filter.compiler.d.ts +49 -0
  39. package/src/lib/workflow-engine/approval-instance-field-filter.compiler.js +501 -0
  40. package/src/lib/workflow-engine/approval-instance-field-filter.compiler.js.map +1 -0
  41. package/src/lib/workflow-engine/approval-instance-filterable-field.policy.d.ts +15 -0
  42. package/src/lib/workflow-engine/approval-instance-filterable-field.policy.js +20 -0
  43. package/src/lib/workflow-engine/approval-instance-filterable-field.policy.js.map +1 -0
  44. package/src/lib/workflow-engine/dto/approval-instance-field-filter.input.d.ts +15 -0
  45. package/src/lib/workflow-engine/dto/approval-instance-field-filter.input.js +55 -0
  46. package/src/lib/workflow-engine/dto/approval-instance-field-filter.input.js.map +1 -0
  47. package/src/lib/workflow-engine/dto/approval-instance-list-args.d.ts +9 -0
  48. package/src/lib/workflow-engine/dto/approval-instance-list-args.js +24 -0
  49. package/src/lib/workflow-engine/dto/approval-instance-list-args.js.map +1 -0
  50. package/src/lib/workflow-engine/dto/approval-instance-sort.input.d.ts +10 -0
  51. package/src/lib/workflow-engine/dto/approval-instance-sort.input.js +32 -0
  52. package/src/lib/workflow-engine/dto/approval-instance-sort.input.js.map +1 -0
  53. package/src/lib/workflow-engine/workflow-engine.enums.d.ts +12 -0
  54. package/src/lib/workflow-engine/workflow-engine.enums.js +21 -1
  55. package/src/lib/workflow-engine/workflow-engine.enums.js.map +1 -1
  56. package/src/lib/workflow-engine/workflow-engine.queries.d.ts +5 -3
  57. package/src/lib/workflow-engine/workflow-engine.queries.js +31 -9
  58. package/src/lib/workflow-engine/workflow-engine.queries.js.map +1 -1
  59. package/src/lib/workflow-engine/workflow-engine.service.d.ts +35 -4
  60. package/src/lib/workflow-engine/workflow-engine.service.js +266 -53
  61. package/src/lib/workflow-engine/workflow-engine.service.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/migrations/index.ts"],"names":[],"mappings":";;;;AACA,0GAAmG;AACnG,sHAA+G;AAC/G,oGAA6F;AAC7F,8GAAuG;AACvG,0GAAmG;AACnG,sFAAgF;AAChF,wFAAkF;AAClF,kGAA4F;AAC5F,8GAAuG;AACvG,oFAA8E;AAC9E,4GAAqG;AACrG,sHAA8G;AAC9G,8GAAuG;AACvG,kGAA2F;AAC3F,oGAA8F;AAC9F,kIAA0H;AAC1H,8GAAsG;AACtG,sFAAgF;AAChF,8FAAwF;AACxF,8GAAuG;AACvG,0GAAkG;AAClG,gGAA0F;AAC1F,4GAAmG;AACnG,4GAAqG;AACrG,0GAAmG;AACnG,oGAA6F;AAC7F,kHAA0G;AAC1G,kHAA0G;AAC1G,oGAA6F;AAC7F,sFAA+E;AAC/E,0HAAkH;AAErG,QAAA,mBAAmB,GAA8C;IAC5E,iFAAqC;IACrC,6FAA2C;IAC3C,2EAAkC;IAClC,qFAAuC;IACvC,iFAAqC;IACrC,8DAA4B;IAC5B,gEAA6B;IAC7B,0EAAkC;IAClC,qFAAuC;IACvC,4DAA2B;IAC3B,mFAAsC;IACtC,4FAA0C;IAC1C,qFAAuC;IACvC,yEAAiC;IACjC,4EAAmC;IACnC,wGAAgD;IAChD,oFAAsC;IACtC,8DAA4B;IAC5B,sEAAgC;IAChC,qFAAuC;IACvC,gFAAoC;IACpC,wEAAiC;IACjC,iFAAoC;IACpC,mFAAsC;IACtC,iFAAqC;IACrC,2EAAkC;IAClC,wFAAwC;IACxC,wFAAwC;IACxC,2EAAkC;IAClC,6DAA2B;IAC3B,gGAA4C;CAC7C,CAAC;AAEF,qFAA2D;AAC3D,2FAAiE;AACjE,kFAAwD;AACxD,uFAA6D;AAC7D,qFAA2D;AAC3D,2EAAiD;AACjD,4EAAkD;AAClD,iFAAuD;AACvD,uFAA6D;AAC7D,0EAAgD;AAChD,sFAA4D;AAC5D,2FAAiE;AACjE,uFAA6D;AAC7D,iFAAuD;AACvD,kFAAwD;AACxD,iGAAuE;AACvE,uFAA6D;AAC7D,2EAAiD;AACjD,+EAAqD;AACrD,uFAA6D;AAC7D,qFAA2D;AAC3D,gFAAsD;AACtD,sFAA4D;AAC5D,sFAA4D;AAC5D,qFAA2D;AAC3D,kFAAwD;AACxD,yFAA+D;AAC/D,yFAA+D;AAC/D,kFAAwD;AACxD,2EAAiD;AACjD,6FAAmE"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/migrations/index.ts"],"names":[],"mappings":";;;;AACA,0GAAmG;AACnG,sHAA+G;AAC/G,oGAA6F;AAC7F,8GAAuG;AACvG,0GAAmG;AACnG,sFAAgF;AAChF,wFAAkF;AAClF,kGAA4F;AAC5F,8GAAuG;AACvG,oFAA8E;AAC9E,4GAAqG;AACrG,sHAA8G;AAC9G,8GAAuG;AACvG,kGAA2F;AAC3F,oGAA8F;AAC9F,kIAA0H;AAC1H,8GAAsG;AACtG,sFAAgF;AAChF,8FAAwF;AACxF,8GAAuG;AACvG,0GAAkG;AAClG,gGAA0F;AAC1F,4GAAmG;AACnG,4GAAqG;AACrG,0GAAmG;AACnG,oGAA6F;AAC7F,kHAA0G;AAC1G,kHAA0G;AAC1G,oGAA6F;AAC7F,sFAA+E;AAC/E,0HAAkH;AAClH,oHAA2G;AAE9F,QAAA,mBAAmB,GAA8C;IAC5E,iFAAqC;IACrC,6FAA2C;IAC3C,2EAAkC;IAClC,qFAAuC;IACvC,iFAAqC;IACrC,8DAA4B;IAC5B,gEAA6B;IAC7B,0EAAkC;IAClC,qFAAuC;IACvC,4DAA2B;IAC3B,mFAAsC;IACtC,4FAA0C;IAC1C,qFAAuC;IACvC,yEAAiC;IACjC,4EAAmC;IACnC,wGAAgD;IAChD,oFAAsC;IACtC,8DAA4B;IAC5B,sEAAgC;IAChC,qFAAuC;IACvC,gFAAoC;IACpC,wEAAiC;IACjC,iFAAoC;IACpC,mFAAsC;IACtC,iFAAqC;IACrC,2EAAkC;IAClC,wFAAwC;IACxC,wFAAwC;IACxC,2EAAkC;IAClC,6DAA2B;IAC3B,gGAA4C;IAC5C,yFAAwC;CACzC,CAAC;AAEF,qFAA2D;AAC3D,2FAAiE;AACjE,kFAAwD;AACxD,uFAA6D;AAC7D,qFAA2D;AAC3D,2EAAiD;AACjD,4EAAkD;AAClD,iFAAuD;AACvD,uFAA6D;AAC7D,0EAAgD;AAChD,sFAA4D;AAC5D,2FAAiE;AACjE,uFAA6D;AAC7D,iFAAuD;AACvD,kFAAwD;AACxD,iGAAuE;AACvE,uFAA6D;AAC7D,2EAAiD;AACjD,+EAAqD;AACrD,uFAA6D;AAC7D,qFAA2D;AAC3D,gFAAsD;AACtD,sFAA4D;AAC5D,sFAA4D;AAC5D,qFAA2D;AAC3D,kFAAwD;AACxD,yFAA+D;AAC/D,yFAA+D;AAC/D,kFAAwD;AACxD,2EAAiD;AACjD,6FAAmE;AACnE,0FAAgE"}
@@ -0,0 +1,49 @@
1
+ import { FilterableFieldIssue } from '@rytass/bpm-core-shared';
2
+ import type { FormDefinitionSchema } from '@rytass/bpm-core-shared/form';
3
+ import type { EntityManager } from 'typeorm';
4
+ /**
5
+ * The enable check of ADR 25 §5.4, run against the database: which filterable
6
+ * fields of a schema may not take effect for a template (or for every template
7
+ * that shares a form definition), given the instances already stored.
8
+ *
9
+ * Every function takes the `EntityManager` it should read through, so a publish
10
+ * inside a transaction sees the same snapshot as the rest of that transaction.
11
+ * Only the filterable paths are read from `form_data`: nothing else is loaded.
12
+ */
13
+ export interface FilterableFieldIssueReport {
14
+ readonly templateId: string;
15
+ readonly templateName: string;
16
+ readonly issue: FilterableFieldIssue;
17
+ }
18
+ /**
19
+ * Issues that block a template from using `schema`. Empty when the schema has
20
+ * no filterable field, which skips every query.
21
+ *
22
+ * `readInForceSchema`, when given, reads the form schema of the template's
23
+ * current version (called only when `schema` has a filterable field), under the template row lock a publish or rollback holds. Its
24
+ * filterable fields are already guaranteed by the stored data: each was
25
+ * checked against every instance when it became filterable, and every write
26
+ * since has been checked against it under the same lock (ADR 25 §6, §15). So
27
+ * only the paths that are new here, or whose field type changed, are scanned;
28
+ * a publish that enables nothing reads no instance at all. Without it (the
29
+ * designer's read-only check), every filterable path is scanned.
30
+ */
31
+ export declare function readTemplateFilterableFieldIssues(manager: EntityManager, templateId: string, schema: FormDefinitionSchema | null | undefined, readInForceSchema?: () => Promise<FormDefinitionSchema | null>): Promise<readonly FilterableFieldIssueReport[]>;
32
+ /**
33
+ * Throws a conflict that lists every blocking issue, one per line. Pass a
34
+ * reader of the current version's schema as `readInForceSchema` (resolving to
35
+ * null when the template has no published version) to scan only what this
36
+ * change makes filterable.
37
+ */
38
+ export declare function assertTemplateFilterableFieldsEnabled(manager: EntityManager, templateId: string, schema: FormDefinitionSchema | null | undefined, readInForceSchema?: () => Promise<FormDefinitionSchema | null>): Promise<void>;
39
+ /**
40
+ * The designer's view: every template that has instances on a version bound
41
+ * to `formDefinitionId`, checked against `schema`. A form definition can be
42
+ * shared by several templates, so one edit may touch more than one.
43
+ */
44
+ export declare function readFormDefinitionFilterableFieldIssues(manager: EntityManager, formDefinitionId: string, schema: FormDefinitionSchema | null | undefined): Promise<readonly FilterableFieldIssueReport[]>;
45
+ /**
46
+ * Parses the `schemaJson` argument of the designer query. A value that is not
47
+ * a JSON object is a bad request, not an empty schema.
48
+ */
49
+ export declare function readFilterableFieldSchemaFromJson(schemaJson: string): FormDefinitionSchema;
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.readTemplateFilterableFieldIssues = readTemplateFilterableFieldIssues;
4
+ exports.assertTemplateFilterableFieldsEnabled = assertTemplateFilterableFieldsEnabled;
5
+ exports.readFormDefinitionFilterableFieldIssues = readFormDefinitionFilterableFieldIssues;
6
+ exports.readFilterableFieldSchemaFromJson = readFilterableFieldSchemaFromJson;
7
+ const common_1 = require("@nestjs/common");
8
+ const bpm_core_shared_1 = require("@rytass/bpm-core-shared");
9
+ /**
10
+ * Issues that block a template from using `schema`. Empty when the schema has
11
+ * no filterable field, which skips every query.
12
+ *
13
+ * `readInForceSchema`, when given, reads the form schema of the template's
14
+ * current version (called only when `schema` has a filterable field), under the template row lock a publish or rollback holds. Its
15
+ * filterable fields are already guaranteed by the stored data: each was
16
+ * checked against every instance when it became filterable, and every write
17
+ * since has been checked against it under the same lock (ADR 25 §6, §15). So
18
+ * only the paths that are new here, or whose field type changed, are scanned;
19
+ * a publish that enables nothing reads no instance at all. Without it (the
20
+ * designer's read-only check), every filterable path is scanned.
21
+ */
22
+ async function readTemplateFilterableFieldIssues(manager, templateId, schema, readInForceSchema) {
23
+ const paths = (0, bpm_core_shared_1.readFilterableFieldPaths)(schema);
24
+ if (paths.length === 0) {
25
+ return [];
26
+ }
27
+ const scannedPaths = readInForceSchema === undefined
28
+ ? paths
29
+ : readNewlyFilterablePaths(paths, await readInForceSchema());
30
+ const history = await readHistoryFormVersions(manager, templateId);
31
+ const instances = scannedPaths.length === 0
32
+ ? []
33
+ : await readInstanceFilterableValues(manager, templateId, scannedPaths.map((item) => item.tableKey ?? item.key));
34
+ const issues = (0, bpm_core_shared_1.readFilterableFieldIssues)({
35
+ history: history.map((row) => ({
36
+ schema: row.schema,
37
+ versionNumber: Number(row.versionNumber),
38
+ })),
39
+ instances,
40
+ schema,
41
+ });
42
+ if (issues.length === 0) {
43
+ return [];
44
+ }
45
+ const templateName = await readTemplateName(manager, templateId);
46
+ return issues.map((issue) => ({ issue, templateId, templateName }));
47
+ }
48
+ /**
49
+ * Throws a conflict that lists every blocking issue, one per line. Pass a
50
+ * reader of the current version's schema as `readInForceSchema` (resolving to
51
+ * null when the template has no published version) to scan only what this
52
+ * change makes filterable.
53
+ */
54
+ async function assertTemplateFilterableFieldsEnabled(manager, templateId, schema, readInForceSchema) {
55
+ const reports = await readTemplateFilterableFieldIssues(manager, templateId, schema, readInForceSchema);
56
+ if (reports.length > 0) {
57
+ throw new common_1.ConflictException(reports.map((report) => (0, bpm_core_shared_1.describeFilterableFieldIssue)(report.issue)).join('\n'));
58
+ }
59
+ }
60
+ /**
61
+ * The designer's view: every template that has instances on a version bound
62
+ * to `formDefinitionId`, checked against `schema`. A form definition can be
63
+ * shared by several templates, so one edit may touch more than one.
64
+ */
65
+ async function readFormDefinitionFilterableFieldIssues(manager, formDefinitionId, schema) {
66
+ if ((0, bpm_core_shared_1.readFilterableFieldPaths)(schema).length === 0) {
67
+ return [];
68
+ }
69
+ const rows = await manager.query(`SELECT DISTINCT tv.template_id AS "templateId"
70
+ FROM approval_template_versions tv
71
+ JOIN form_definition_versions fv ON fv.id = tv.form_definition_version_id
72
+ JOIN approval_templates t ON t.id = tv.template_id AND t.deleted_at IS NULL
73
+ WHERE fv.form_definition_id = $1
74
+ AND EXISTS (
75
+ SELECT 1 FROM approval_instances i WHERE i.template_version_id = tv.id
76
+ )`, [formDefinitionId]);
77
+ const reports = await Promise.all(rows.map((row) => readTemplateFilterableFieldIssues(manager, row.templateId, schema)));
78
+ return reports.flat();
79
+ }
80
+ /**
81
+ * The paths of `paths` that `inForceSchema` does not already hold as
82
+ * filterable with the same field type: a field made filterable, a column
83
+ * moved into a new table path, or a type change (which changes what a stored
84
+ * value must look like).
85
+ */
86
+ function readNewlyFilterablePaths(paths, inForceSchema) {
87
+ const inForceTypes = new Map((0, bpm_core_shared_1.readFilterableFieldPaths)(inForceSchema).map((item) => [item.path, item.field.type]));
88
+ return paths.filter((item) => inForceTypes.get(item.path) !== item.field.type);
89
+ }
90
+ /**
91
+ * Parses the `schemaJson` argument of the designer query. A value that is not
92
+ * a JSON object is a bad request, not an empty schema.
93
+ */
94
+ function readFilterableFieldSchemaFromJson(schemaJson) {
95
+ let parsed;
96
+ try {
97
+ parsed = JSON.parse(schemaJson);
98
+ }
99
+ catch (error) {
100
+ throw new common_1.BadRequestException(`schemaJson is not valid JSON: ${error instanceof Error ? error.message : 'unknown error'}`);
101
+ }
102
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
103
+ throw new common_1.BadRequestException('schemaJson must be an object');
104
+ }
105
+ return parsed;
106
+ }
107
+ /**
108
+ * The form versions that the template's instances were created under, each
109
+ * once. A type conflict is judged against these, not against every version
110
+ * that was ever drafted.
111
+ */
112
+ async function readHistoryFormVersions(manager, templateId) {
113
+ const rows = await manager.query(`SELECT DISTINCT fv.id, fv.version AS "versionNumber", fv.schema
114
+ FROM approval_template_versions tv
115
+ JOIN form_definition_versions fv ON fv.id = tv.form_definition_version_id
116
+ WHERE tv.template_id = $1
117
+ AND EXISTS (
118
+ SELECT 1 FROM approval_instances i WHERE i.template_version_id = tv.id
119
+ )`, [templateId]);
120
+ return rows;
121
+ }
122
+ /**
123
+ * The stored value of each filterable key, for every instance of the template.
124
+ * The key list is a bound parameter, and a key the instance does not have is
125
+ * left out of its object, which the checks read as "no value".
126
+ */
127
+ async function readInstanceFilterableValues(manager, templateId, keys) {
128
+ const uniqueKeys = [...new Set(keys)];
129
+ const rows = await manager.query(`SELECT i.id,
130
+ (SELECT jsonb_object_agg(k, i.form_data -> k)
131
+ FROM unnest($2::text[]) AS k
132
+ WHERE i.form_data ? k) AS form_data
133
+ FROM approval_instances i
134
+ WHERE i.template_id = $1`, [templateId, uniqueKeys]);
135
+ return rows.map((row) => ({ formData: row.form_data, id: row.id }));
136
+ }
137
+ async function readTemplateName(manager, templateId) {
138
+ const rows = await manager.query(`SELECT name FROM approval_templates WHERE id = $1`, [templateId]);
139
+ return rows[0]?.name ?? '';
140
+ }
141
+ //# sourceMappingURL=filterable-field-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterable-field-guard.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/filterable-field-guard.ts"],"names":[],"mappings":";;AA0DA,8EAyCC;AAQD,sFAkBC;AAOD,0FA2BC;AA2BD,8EAkBC;AA5MD,2CAAwE;AACxE,6DAMiC;AAsCjC;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,iCAAiC,CACrD,OAAsB,EACtB,UAAkB,EAClB,MAA+C,EAC/C,iBAA8D;IAE9D,MAAM,KAAK,GAAG,IAAA,0CAAwB,EAAC,MAAM,CAAC,CAAC;IAE/C,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,YAAY,GAChB,iBAAiB,KAAK,SAAS;QAC7B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,wBAAwB,CAAC,KAAK,EAAE,MAAM,iBAAiB,EAAE,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnE,MAAM,SAAS,GACb,YAAY,CAAC,MAAM,KAAK,CAAC;QACvB,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,MAAM,4BAA4B,CAChC,OAAO,EACP,UAAU,EACV,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,GAAG,CAAC,CACtD,CAAC;IACR,MAAM,MAAM,GAAG,IAAA,2CAAyB,EAAC;QACvC,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;YAC7B,MAAM,EAAE,GAAG,CAAC,MAAM;YAClB,aAAa,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;SACzC,CAAC,CAAC;QACH,SAAS;QACT,MAAM;KACP,CAAC,CAAC;IAEH,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAEjE,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;;;GAKG;AACI,KAAK,UAAU,qCAAqC,CACzD,OAAsB,EACtB,UAAkB,EAClB,MAA+C,EAC/C,iBAA8D;IAE9D,MAAM,OAAO,GAAG,MAAM,iCAAiC,CACrD,OAAO,EACP,UAAU,EACV,MAAM,EACN,iBAAiB,CAClB,CAAC;IAEF,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,0BAAiB,CACzB,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,IAAA,8CAA4B,EAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAC/E,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;GAIG;AACI,KAAK,UAAU,uCAAuC,CAC3D,OAAsB,EACtB,gBAAwB,EACxB,MAA+C;IAE/C,IAAI,IAAA,0CAAwB,EAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,IAAI,GAAyC,MAAM,OAAO,CAAC,KAAK,CACpE;;;;;;;UAOM,EACN,CAAC,gBAAgB,CAAC,CACnB,CAAC;IACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CACf,iCAAiC,CAAC,OAAO,EAAE,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CACnE,CACF,CAAC;IAEF,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;AACxB,CAAC;AAED;;;;;GAKG;AACH,SAAS,wBAAwB,CAC/B,KAAqC,EACrC,aAA0C;IAE1C,MAAM,YAAY,GAAG,IAAI,GAAG,CAC1B,IAAA,0CAAwB,EAAC,aAAa,CAAC,CAAC,GAAG,CACzC,CAAC,IAAI,EAA6B,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAClE,CACF,CAAC;IAEF,OAAO,KAAK,CAAC,MAAM,CACjB,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,CAC1D,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAgB,iCAAiC,CAC/C,UAAkB;IAElB,IAAI,MAAe,CAAC;IAEpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAY,CAAC;IAC7C,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACxB,MAAM,IAAI,4BAAmB,CAC3B,iCAAiC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAC5F,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3E,MAAM,IAAI,4BAAmB,CAAC,8BAA8B,CAAC,CAAC;IAChE,CAAC;IAED,OAAO,MAA8B,CAAC;AACxC,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,uBAAuB,CACpC,OAAsB,EACtB,UAAkB;IAElB,MAAM,IAAI,GAAqC,MAAM,OAAO,CAAC,KAAK,CAChE;;;;;;UAMM,EACN,CAAC,UAAU,CAAC,CACb,CAAC;IAEF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,4BAA4B,CACzC,OAAsB,EACtB,UAAkB,EAClB,IAAuB;IAEvB,MAAM,UAAU,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IACtC,MAAM,IAAI,GAAmC,MAAM,OAAO,CAAC,KAAK,CAC9D;;;;;+BAK2B,EAC3B,CAAC,UAAU,EAAE,UAAU,CAAC,CACzB,CAAC;IAEF,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,KAAK,UAAU,gBAAgB,CAC7B,OAAsB,EACtB,UAAkB;IAElB,MAAM,IAAI,GAA+B,MAAM,OAAO,CAAC,KAAK,CAC1D,mDAAmD,EACnD,CAAC,UAAU,CAAC,CACb,CAAC;IAEF,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,EAAE,CAAC;AAC7B,CAAC"}
@@ -0,0 +1,21 @@
1
+ export declare enum FilterableFieldIssueKind {
2
+ TYPE_CHANGED = "TYPE_CHANGED",
3
+ INVALID_VALUES = "INVALID_VALUES"
4
+ }
5
+ /**
6
+ * One reason a field cannot be marked filterable yet (ADR 25 §5.4). Only the
7
+ * fields that matter for the kind are filled: `conflictVersionNumbers` for a
8
+ * type change, `invalidInstanceCount` and `sampleInstanceIds` for bad values.
9
+ */
10
+ export declare class FilterableFieldIssueObject {
11
+ kind: FilterableFieldIssueKind;
12
+ path: string;
13
+ label: string;
14
+ fieldType: string;
15
+ templateId: string;
16
+ templateName: string;
17
+ message: string;
18
+ conflictVersionNumbers: readonly number[];
19
+ invalidInstanceCount: number;
20
+ sampleInstanceIds: readonly string[];
21
+ }
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FilterableFieldIssueObject = exports.FilterableFieldIssueKind = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_1 = require("@nestjs/graphql");
6
+ var FilterableFieldIssueKind;
7
+ (function (FilterableFieldIssueKind) {
8
+ FilterableFieldIssueKind["TYPE_CHANGED"] = "TYPE_CHANGED";
9
+ FilterableFieldIssueKind["INVALID_VALUES"] = "INVALID_VALUES";
10
+ })(FilterableFieldIssueKind || (exports.FilterableFieldIssueKind = FilterableFieldIssueKind = {}));
11
+ (0, graphql_1.registerEnumType)(FilterableFieldIssueKind, {
12
+ name: 'FilterableFieldIssueKind',
13
+ });
14
+ /**
15
+ * One reason a field cannot be marked filterable yet (ADR 25 §5.4). Only the
16
+ * fields that matter for the kind are filled: `conflictVersionNumbers` for a
17
+ * type change, `invalidInstanceCount` and `sampleInstanceIds` for bad values.
18
+ */
19
+ let FilterableFieldIssueObject = class FilterableFieldIssueObject {
20
+ };
21
+ exports.FilterableFieldIssueObject = FilterableFieldIssueObject;
22
+ tslib_1.__decorate([
23
+ (0, graphql_1.Field)(() => FilterableFieldIssueKind),
24
+ tslib_1.__metadata("design:type", String)
25
+ ], FilterableFieldIssueObject.prototype, "kind", void 0);
26
+ tslib_1.__decorate([
27
+ (0, graphql_1.Field)(() => String),
28
+ tslib_1.__metadata("design:type", String)
29
+ ], FilterableFieldIssueObject.prototype, "path", void 0);
30
+ tslib_1.__decorate([
31
+ (0, graphql_1.Field)(() => String),
32
+ tslib_1.__metadata("design:type", String)
33
+ ], FilterableFieldIssueObject.prototype, "label", void 0);
34
+ tslib_1.__decorate([
35
+ (0, graphql_1.Field)(() => String),
36
+ tslib_1.__metadata("design:type", String)
37
+ ], FilterableFieldIssueObject.prototype, "fieldType", void 0);
38
+ tslib_1.__decorate([
39
+ (0, graphql_1.Field)(() => graphql_1.ID),
40
+ tslib_1.__metadata("design:type", String)
41
+ ], FilterableFieldIssueObject.prototype, "templateId", void 0);
42
+ tslib_1.__decorate([
43
+ (0, graphql_1.Field)(() => String),
44
+ tslib_1.__metadata("design:type", String)
45
+ ], FilterableFieldIssueObject.prototype, "templateName", void 0);
46
+ tslib_1.__decorate([
47
+ (0, graphql_1.Field)(() => String),
48
+ tslib_1.__metadata("design:type", String)
49
+ ], FilterableFieldIssueObject.prototype, "message", void 0);
50
+ tslib_1.__decorate([
51
+ (0, graphql_1.Field)(() => [graphql_1.Int]),
52
+ tslib_1.__metadata("design:type", Array)
53
+ ], FilterableFieldIssueObject.prototype, "conflictVersionNumbers", void 0);
54
+ tslib_1.__decorate([
55
+ (0, graphql_1.Field)(() => graphql_1.Int),
56
+ tslib_1.__metadata("design:type", Number)
57
+ ], FilterableFieldIssueObject.prototype, "invalidInstanceCount", void 0);
58
+ tslib_1.__decorate([
59
+ (0, graphql_1.Field)(() => [String]),
60
+ tslib_1.__metadata("design:type", Array)
61
+ ], FilterableFieldIssueObject.prototype, "sampleInstanceIds", void 0);
62
+ exports.FilterableFieldIssueObject = FilterableFieldIssueObject = tslib_1.__decorate([
63
+ (0, graphql_1.ObjectType)('FilterableFieldIssue')
64
+ ], FilterableFieldIssueObject);
65
+ //# sourceMappingURL=filterable-field-issue.object.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterable-field-issue.object.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/filterable-field-issue.object.ts"],"names":[],"mappings":";;;;AAAA,6CAA+E;AAE/E,IAAY,wBAGX;AAHD,WAAY,wBAAwB;IAClC,yDAA6B,CAAA;IAC7B,6DAAiC,CAAA;AACnC,CAAC,EAHW,wBAAwB,wCAAxB,wBAAwB,QAGnC;AAED,IAAA,0BAAgB,EAAC,wBAAwB,EAAE;IACzC,IAAI,EAAE,0BAA0B;CACjC,CAAC,CAAC;AAEH;;;;GAIG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;CA8BtC,CAAA;AA9BY,gEAA0B;AAErC;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,wBAAwB,CAAC;;wDACN;AAGhC;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;wDACN;AAGd;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;yDACL;AAGf;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;6DACD;AAGnB;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,YAAE,CAAC;;8DACI;AAGpB;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;gEACE;AAGtB;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,MAAM,CAAC;;2DACH;AAGjB;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,CAAC,aAAG,CAAC,CAAC;;0EACwB;AAG3C;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,aAAG,CAAC;;wEACa;AAG9B;IADC,IAAA,eAAK,EAAC,GAAG,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;;qEACgB;qCA7B3B,0BAA0B;IADtC,IAAA,oBAAU,EAAC,sBAAsB,CAAC;GACtB,0BAA0B,CA8BtC"}
@@ -0,0 +1,20 @@
1
+ import { Repository } from 'typeorm';
2
+ import { ApprovalTemplateEntity } from './approval-template.entity';
3
+ import { FilterableFieldIssueObject } from './filterable-field-issue.object';
4
+ /**
5
+ * Read-only check for the designer: does the schema in the editor conflict
6
+ * with what a template already stored? It blocks nothing. The publish itself
7
+ * is refused by `TemplateService` (ADR 25 §5.4).
8
+ *
9
+ * Designer-only, not merely authenticated: the answer names templates and
10
+ * instance ids, which a plain member has no business reading.
11
+ */
12
+ export declare class FilterableFieldQueries {
13
+ private readonly templateRepository;
14
+ constructor(templateRepository: Repository<ApprovalTemplateEntity>);
15
+ /**
16
+ * Both ids given: only that template. Only `formDefinitionId`: every
17
+ * template on that form definition. Neither: nothing to check.
18
+ */
19
+ filterableFieldIssues(templateId: string | null | undefined, formDefinitionId: string | null | undefined, schemaJson: string): Promise<readonly FilterableFieldIssueObject[]>;
20
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FilterableFieldQueries = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const graphql_1 = require("@nestjs/graphql");
6
+ const typeorm_1 = require("@nestjs/typeorm");
7
+ const bpm_core_shared_1 = require("@rytass/bpm-core-shared");
8
+ const typeorm_2 = require("typeorm");
9
+ const bpm_auth_1 = require("../bpm-auth");
10
+ const approval_template_entity_1 = require("./approval-template.entity");
11
+ const filterable_field_issue_object_1 = require("./filterable-field-issue.object");
12
+ const filterable_field_guard_1 = require("./filterable-field-guard");
13
+ /**
14
+ * Read-only check for the designer: does the schema in the editor conflict
15
+ * with what a template already stored? It blocks nothing. The publish itself
16
+ * is refused by `TemplateService` (ADR 25 §5.4).
17
+ *
18
+ * Designer-only, not merely authenticated: the answer names templates and
19
+ * instance ids, which a plain member has no business reading.
20
+ */
21
+ let FilterableFieldQueries = class FilterableFieldQueries {
22
+ constructor(templateRepository) {
23
+ this.templateRepository = templateRepository;
24
+ }
25
+ /**
26
+ * Both ids given: only that template. Only `formDefinitionId`: every
27
+ * template on that form definition. Neither: nothing to check.
28
+ */
29
+ async filterableFieldIssues(templateId, formDefinitionId, schemaJson) {
30
+ const schema = (0, filterable_field_guard_1.readFilterableFieldSchemaFromJson)(schemaJson);
31
+ const manager = this.templateRepository.manager;
32
+ const reports = await readIssueReports(manager, templateId ?? null, formDefinitionId ?? null, schema);
33
+ return reports.map(toFilterableFieldIssueObject);
34
+ }
35
+ };
36
+ exports.FilterableFieldQueries = FilterableFieldQueries;
37
+ tslib_1.__decorate([
38
+ (0, graphql_1.Query)(() => [filterable_field_issue_object_1.FilterableFieldIssueObject]),
39
+ tslib_1.__param(0, (0, graphql_1.Args)('templateId', { nullable: true, type: () => graphql_1.ID })),
40
+ tslib_1.__param(1, (0, graphql_1.Args)('formDefinitionId', { nullable: true, type: () => graphql_1.ID })),
41
+ tslib_1.__param(2, (0, graphql_1.Args)('schemaJson', { type: () => String })),
42
+ tslib_1.__metadata("design:type", Function),
43
+ tslib_1.__metadata("design:paramtypes", [Object, Object, String]),
44
+ tslib_1.__metadata("design:returntype", Promise)
45
+ ], FilterableFieldQueries.prototype, "filterableFieldIssues", null);
46
+ exports.FilterableFieldQueries = FilterableFieldQueries = tslib_1.__decorate([
47
+ (0, graphql_1.Resolver)(),
48
+ (0, bpm_auth_1.BPMDesignerOnly)(),
49
+ tslib_1.__param(0, (0, typeorm_1.InjectRepository)(approval_template_entity_1.ApprovalTemplateEntity)),
50
+ tslib_1.__metadata("design:paramtypes", [typeorm_2.Repository])
51
+ ], FilterableFieldQueries);
52
+ async function readIssueReports(manager, templateId, formDefinitionId, schema) {
53
+ if (templateId) {
54
+ return (0, filterable_field_guard_1.readTemplateFilterableFieldIssues)(manager, templateId, schema);
55
+ }
56
+ if (formDefinitionId) {
57
+ return (0, filterable_field_guard_1.readFormDefinitionFilterableFieldIssues)(manager, formDefinitionId, schema);
58
+ }
59
+ return [];
60
+ }
61
+ function toFilterableFieldIssueObject(report) {
62
+ const { issue } = report;
63
+ return Object.assign(new filterable_field_issue_object_1.FilterableFieldIssueObject(), {
64
+ conflictVersionNumbers: issue.kind === 'TYPE_CHANGED'
65
+ ? issue.conflicts.map((conflict) => conflict.versionNumber)
66
+ : [],
67
+ fieldType: issue.type,
68
+ invalidInstanceCount: issue.kind === 'INVALID_VALUES' ? issue.invalidInstanceCount : 0,
69
+ kind: filterable_field_issue_object_1.FilterableFieldIssueKind[issue.kind],
70
+ label: issue.label,
71
+ message: (0, bpm_core_shared_1.describeFilterableFieldIssue)(issue),
72
+ path: issue.path,
73
+ sampleInstanceIds: issue.kind === 'INVALID_VALUES'
74
+ ? [...new Set(issue.samples.map((sample) => sample.instanceId))]
75
+ : [],
76
+ templateId: report.templateId,
77
+ templateName: report.templateName,
78
+ });
79
+ }
80
+ //# sourceMappingURL=filterable-field.queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filterable-field.queries.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/filterable-field.queries.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ export * from './dto/approval-template.input';
6
6
  export * from './dto/compose-approval-template.input';
7
7
  export * from './dto/expression-designer.dto';
8
8
  export * from './expression-designer.service';
9
+ export * from './filterable-field-issue.object';
9
10
  export * from './template-observer.token';
10
11
  export * from './template.enums';
11
12
  export * from './template.module';
@@ -9,6 +9,7 @@ tslib_1.__exportStar(require("./dto/approval-template.input"), exports);
9
9
  tslib_1.__exportStar(require("./dto/compose-approval-template.input"), exports);
10
10
  tslib_1.__exportStar(require("./dto/expression-designer.dto"), exports);
11
11
  tslib_1.__exportStar(require("./expression-designer.service"), exports);
12
+ tslib_1.__exportStar(require("./filterable-field-issue.object"), exports);
12
13
  tslib_1.__exportStar(require("./template-observer.token"), exports);
13
14
  tslib_1.__exportStar(require("./template.enums"), exports);
14
15
  tslib_1.__exportStar(require("./template.module"), exports);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/index.ts"],"names":[],"mappings":";;;AAAA,8EAAoD;AACpD,6EAAmD;AACnD,qEAA2C;AAC3C,6EAAmD;AACnD,wEAA8C;AAC9C,gFAAsD;AACtD,wEAA8C;AAC9C,wEAA8C;AAC9C,oEAA0C;AAC1C,2DAAiC;AACjC,4DAAkC;AAClC,6DAAmC;AACnC,0EAAgD"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/index.ts"],"names":[],"mappings":";;;AAAA,8EAAoD;AACpD,6EAAmD;AACnD,qEAA2C;AAC3C,6EAAmD;AACnD,wEAA8C;AAC9C,gFAAsD;AACtD,wEAA8C;AAC9C,wEAA8C;AAC9C,0EAAgD;AAChD,oEAA0C;AAC1C,2DAAiC;AACjC,4DAAkC;AAClC,6DAAmC;AACnC,0EAAgD"}
@@ -13,6 +13,7 @@ const approval_template_version_entity_1 = require("./approval-template-version.
13
13
  const compose_template_mutations_1 = require("./compose-template.mutations");
14
14
  const expression_designer_queries_1 = require("./expression-designer.queries");
15
15
  const expression_designer_service_1 = require("./expression-designer.service");
16
+ const filterable_field_queries_1 = require("./filterable-field.queries");
16
17
  const template_mutations_1 = require("./template.mutations");
17
18
  const template_queries_1 = require("./template.queries");
18
19
  const template_service_1 = require("./template.service");
@@ -35,6 +36,7 @@ exports.TemplateModule = TemplateModule = tslib_1.__decorate([
35
36
  compose_template_mutations_1.ComposeTemplateMutations,
36
37
  expression_designer_queries_1.ExpressionDesignerQueries,
37
38
  expression_designer_service_1.ExpressionDesignerService,
39
+ filterable_field_queries_1.FilterableFieldQueries,
38
40
  template_mutations_1.TemplateMutations,
39
41
  template_queries_1.TemplateQueries,
40
42
  template_service_1.TemplateService,
@@ -1 +1 @@
1
- {"version":3,"file":"template.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/template.module.ts"],"names":[],"mappings":";;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,oEAAgE;AAChE,2FAAqF;AACrF,qDAAiD;AACjD,2FAAqF;AACrF,yEAAoE;AACpE,yFAAmF;AACnF,6EAAwE;AACxE,+EAA0E;AAC1E,+EAA0E;AAC1E,6DAAyD;AACzD,yDAAqD;AACrD,yDAAqD;AAuB9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IArB1B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,kCAAe;YACf,wBAAU;YACV,uBAAa,CAAC,UAAU,CAAC;gBACvB,kEAA8B;gBAC9B,iDAAsB;gBACtB,gEAA6B;gBAC7B,4DAA2B;aAC5B,CAAC;SACH;QACD,SAAS,EAAE;YACT,qDAAwB;YACxB,uDAAyB;YACzB,uDAAyB;YACzB,sCAAiB;YACjB,kCAAe;YACf,kCAAe;SAChB;QACD,OAAO,EAAE,CAAC,kCAAe,CAAC;KAC3B,CAAC;GACW,cAAc,CAAG"}
1
+ {"version":3,"file":"template.module.js","sourceRoot":"","sources":["../../../../../../libs/bpm-core/src/lib/template/template.module.ts"],"names":[],"mappings":";;;;AAAA,2CAAwC;AACxC,6CAAgD;AAChD,oEAAgE;AAChE,2FAAqF;AACrF,qDAAiD;AACjD,2FAAqF;AACrF,yEAAoE;AACpE,yFAAmF;AACnF,6EAAwE;AACxE,+EAA0E;AAC1E,+EAA0E;AAC1E,yEAAoE;AACpE,6DAAyD;AACzD,yDAAqD;AACrD,yDAAqD;AAwB9C,IAAM,cAAc,GAApB,MAAM,cAAc;CAAG,CAAA;AAAjB,wCAAc;yBAAd,cAAc;IAtB1B,IAAA,eAAM,EAAC;QACN,OAAO,EAAE;YACP,kCAAe;YACf,wBAAU;YACV,uBAAa,CAAC,UAAU,CAAC;gBACvB,kEAA8B;gBAC9B,iDAAsB;gBACtB,gEAA6B;gBAC7B,4DAA2B;aAC5B,CAAC;SACH;QACD,SAAS,EAAE;YACT,qDAAwB;YACxB,uDAAyB;YACzB,uDAAyB;YACzB,iDAAsB;YACtB,sCAAiB;YACjB,kCAAe;YACf,kCAAe;SAChB;QACD,OAAO,EAAE,CAAC,kCAAe,CAAC;KAC3B,CAAC;GACW,cAAc,CAAG"}
@@ -73,7 +73,19 @@ export declare class TemplateService {
73
73
  listApprovalTemplateVersions(templateId: string): Promise<readonly ApprovalTemplateVersionEntity[]>;
74
74
  getApprovalTemplateVersion(id: string): Promise<ApprovalTemplateVersionEntity>;
75
75
  updateApprovalTemplateDraft(input: UpdateApprovalTemplateDraftInput, manager?: EntityManager): Promise<ApprovalTemplateVersionEntity>;
76
+ /**
77
+ * Runs `run` in the caller's transaction when one is passed, otherwise in a
78
+ * new one, so a template lock taken inside it is held until the write
79
+ * commits.
80
+ */
81
+ private runInTemplateTransaction;
76
82
  forkApprovalTemplate(templateId: string, manager?: EntityManager): Promise<ApprovalTemplateVersionEntity>;
83
+ /**
84
+ * Forks under the template row lock (ADR 25 §15): the draft check, the
85
+ * source read and the insert see the template as no concurrent publish or
86
+ * fork can change it until this commits.
87
+ */
88
+ private forkApprovalTemplateLocked;
77
89
  publishApprovalTemplateVersion(versionId: string, publishedByMemberId?: string, manager?: EntityManager): Promise<ApprovalTemplateVersionEntity>;
78
90
  /**
79
91
  * The publish itself, without the observer notification. Split out so
@@ -81,6 +93,11 @@ export declare class TemplateService {
81
93
  * and still report a single `COMPOSED` event rather than two.
82
94
  */
83
95
  private publishVersion;
96
+ /**
97
+ * Reads one template row, optionally locked. Locks are only taken inside a
98
+ * transaction; the caller passes the transaction's manager.
99
+ */
100
+ private lockTemplateRow;
84
101
  private publishApprovalTemplateVersionWithManager;
85
102
  rollbackApprovalTemplateVersion(versionId: string, rolledBackByMemberId?: string): Promise<ApprovalTemplateVersionEntity>;
86
103
  /**
@@ -90,6 +107,10 @@ export declare class TemplateService {
90
107
  */
91
108
  private notifyTemplateObserver;
92
109
  private readHostObserver;
110
+ /**
111
+ * Returns the bound form schema so the publish can run the filterable-field
112
+ * check against it without loading the form version a second time.
113
+ */
93
114
  private validatePublishableVersion;
94
115
  /** The cel-legacy publish lint, unchanged (docs/24 §1). */
95
116
  private lintCelLegacyExpressions;
@@ -121,9 +142,27 @@ export declare class TemplateService {
121
142
  private templateVersions;
122
143
  private templateCategories;
123
144
  private formVersions;
145
+ /**
146
+ * The form schema of the template's current version: the one whose
147
+ * filterable fields the stored instances already satisfy. Null when the
148
+ * template has no published version yet. Read under the caller's template
149
+ * row lock, so no write can change what it guarantees before the publish
150
+ * commits.
151
+ */
152
+ private readInForceFormSchema;
153
+ private readFormSchemaOfVersion;
124
154
  private getTemplateOrThrow;
125
155
  private getTemplateCategoryOrThrow;
126
156
  private setApprovalTemplateActive;
157
+ /**
158
+ * Locks the template row FOR UPDATE, the lock a publish, compose or rollback
159
+ * takes (ADR 25 §15), then reads the row with its category. A template edit
160
+ * saves the whole entity it read, so reading it unlocked would let a publish
161
+ * that commits in between be overwritten with the pre-publish
162
+ * `currentVersionId`; under the lock the read is the latest committed row
163
+ * and a publish waits for this edit instead.
164
+ */
165
+ private readLockedTemplateOrThrow;
127
166
  private setApprovalTemplateCategoryActive;
128
167
  private getTemplateVersionOrThrow;
129
168
  private readNextVersionNumber;