@contrail/documents 1.6.0-alpha.ws.2 → 1.6.0-alpha.ws.3

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/CHANGELOG.md CHANGED
@@ -11,6 +11,7 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
11
11
 
12
12
  - Document transaction contract types for the transactional write path: `DocumentOperation`, `DocumentElementPatch`, `WriteTransactionRequest`, and `WriteTransactionResponse`.
13
13
  - `DocumentWriteMode` type and an optional `writeMode` field on the `Document` interface, used to gate the transactional write path.
14
+ - `DocumentTransactionMessage` — the WebSocket broadcast shape for a committed transaction (carries `sequenceNumber`, `clientTransactionId`, and inline `operations` or an `operationsDownloadUrl`).
14
15
 
15
16
  ## [1.5.6] - 2026-04-29
16
17
 
package/lib/index.d.ts CHANGED
@@ -3,7 +3,6 @@ export * from './components';
3
3
  export * from './document-element-factory';
4
4
  export * from './document-element-property-binding-handler';
5
5
  export * from './document-action';
6
- export * from './document-transaction-validation';
7
6
  export * from './util/measure-text/measure-text';
8
7
  export * from './util/dynamic-text/dynamic-text-util';
9
8
  export * from './document-element-constants';
package/lib/index.js CHANGED
@@ -19,7 +19,6 @@ __exportStar(require("./components"), exports);
19
19
  __exportStar(require("./document-element-factory"), exports);
20
20
  __exportStar(require("./document-element-property-binding-handler"), exports);
21
21
  __exportStar(require("./document-action"), exports);
22
- __exportStar(require("./document-transaction-validation"), exports);
23
22
  __exportStar(require("./util/measure-text/measure-text"), exports);
24
23
  __exportStar(require("./util/dynamic-text/dynamic-text-util"), exports);
25
24
  __exportStar(require("./document-element-constants"), exports);
@@ -21,3 +21,18 @@ export interface WriteTransactionResponse {
21
21
  createdById: string;
22
22
  clientTransactionId?: string;
23
23
  }
24
+ interface DocumentTransactionMessageBase {
25
+ type: 'DOCUMENT_TRANSACTION';
26
+ documentId: string;
27
+ sequenceNumber: number;
28
+ createdOn: string;
29
+ clientTransactionId?: string;
30
+ }
31
+ export type DocumentTransactionMessage = (DocumentTransactionMessageBase & {
32
+ operations: DocumentOperation[];
33
+ operationsDownloadUrl?: never;
34
+ }) | (DocumentTransactionMessageBase & {
35
+ operationsDownloadUrl: string;
36
+ operations?: never;
37
+ });
38
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@contrail/documents",
3
- "version": "1.6.0-alpha.ws.2",
3
+ "version": "1.6.0-alpha.ws.3",
4
4
  "description": "Documents library for contrail platform",
5
5
  "main": "lib/index.js",
6
6
  "types": "lib/index.d.ts",
@@ -1,16 +0,0 @@
1
- import { WriteTransactionRequest } from './types/document-transaction';
2
- export type WriteTransactionValidationCode = 'OPERATIONS_REQUIRED' | 'UNKNOWN_OPERATION_ACTION' | 'OPERATION_MISSING_ELEMENT' | 'OPERATION_MISSING_ELEMENT_ID' | 'UNKNOWN_ELEMENT_FIELD' | 'INVALID_ELEMENT_FIELD_TYPE' | 'INVALID_CLIENT_TRANSACTION_ID' | 'ELEMENT_DOCUMENT_ID_MISMATCH';
3
- export interface WriteTransactionValidationIssue {
4
- code: WriteTransactionValidationCode;
5
- index?: number;
6
- action?: string;
7
- field?: string;
8
- fields?: string[];
9
- expected?: string;
10
- elementDocumentId?: string;
11
- documentId?: string;
12
- }
13
- export interface ValidateWriteTransactionOptions {
14
- documentId?: string;
15
- }
16
- export declare function validateWriteTransaction(request: WriteTransactionRequest, options?: ValidateWriteTransactionOptions): WriteTransactionValidationIssue[];
@@ -1,175 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validateWriteTransaction = validateWriteTransaction;
4
- const KNOWN_OPERATION_ACTIONS = ['createElement', 'updateElement', 'deleteElement'];
5
- const CODE_RANK = {
6
- OPERATIONS_REQUIRED: 1,
7
- UNKNOWN_OPERATION_ACTION: 2,
8
- OPERATION_MISSING_ELEMENT: 3,
9
- OPERATION_MISSING_ELEMENT_ID: 4,
10
- UNKNOWN_ELEMENT_FIELD: 5,
11
- INVALID_ELEMENT_FIELD_TYPE: 6,
12
- INVALID_CLIENT_TRANSACTION_ID: 7,
13
- ELEMENT_DOCUMENT_ID_MISMATCH: 8,
14
- };
15
- const ELEMENT_FIELD_RULES = {
16
- name: 'string',
17
- size: { numericKeys: ['width', 'height'] },
18
- position: { numericKeys: ['x', 'y', 'z'] },
19
- clipContent: 'boolean',
20
- ownedByReference: 'string',
21
- writeMode: 'string',
22
- style: 'allow',
23
- model: 'allow',
24
- modelBindings: 'allow',
25
- elements: 'allow',
26
- background: 'allow',
27
- importedFrom: 'allow',
28
- startingViewBox: 'allow',
29
- startingLocation: 'allow',
30
- specifiedId: 'string',
31
- type: 'string',
32
- rotate: { numericKeys: ['angle'] },
33
- scale: { numericKeys: ['x', 'y'] },
34
- text: 'string',
35
- url: 'string',
36
- label: 'string',
37
- isLocked: 'boolean',
38
- isHidden: 'boolean',
39
- isTextTool: 'boolean',
40
- documentGenerationConfigId: 'string',
41
- elementIds: 'string[]',
42
- points: 'array',
43
- rowIds: 'string[]',
44
- columnIds: 'string[]',
45
- columnId: 'string',
46
- rowId: 'string',
47
- tableId: 'string',
48
- colspan: 'number',
49
- rowspan: 'number',
50
- imageSize: { numericKeys: ['width', 'height'] },
51
- imagePosition: { numericKeys: ['x', 'y', 'z'] },
52
- alternateUrls: 'allow',
53
- propertyBindings: 'allow',
54
- lineDefinition: 'allow',
55
- annotations: 'allow',
56
- cropDefinition: 'allow',
57
- embedInfo: 'allow',
58
- entityData: 'allow',
59
- start: 'allow',
60
- end: 'allow',
61
- propertyBindingsMetaData: 'allow',
62
- };
63
- function isPlainObject(value) {
64
- return typeof value === 'object' && value !== null && !Array.isArray(value);
65
- }
66
- function collectElementFieldIssues(element, identityFields) {
67
- const issues = [];
68
- for (const [key, value] of Object.entries(element)) {
69
- if (identityFields.includes(key)) {
70
- if (value !== undefined && typeof value !== 'string') {
71
- issues.push({ code: 'INVALID_ELEMENT_FIELD_TYPE', field: key, expected: 'string' });
72
- }
73
- continue;
74
- }
75
- const rule = ELEMENT_FIELD_RULES[key];
76
- if (!rule) {
77
- issues.push({ code: 'UNKNOWN_ELEMENT_FIELD', field: key });
78
- continue;
79
- }
80
- if (value === undefined || value === null || rule === 'allow') {
81
- continue;
82
- }
83
- if (rule === 'string' || rule === 'number' || rule === 'boolean') {
84
- if (typeof value !== rule) {
85
- issues.push({ code: 'INVALID_ELEMENT_FIELD_TYPE', field: key, expected: rule });
86
- }
87
- }
88
- else if (rule === 'string[]') {
89
- if (!Array.isArray(value) || value.some((entry) => typeof entry !== 'string')) {
90
- issues.push({ code: 'INVALID_ELEMENT_FIELD_TYPE', field: key, expected: 'string[]' });
91
- }
92
- }
93
- else if (rule === 'array') {
94
- if (!Array.isArray(value)) {
95
- issues.push({ code: 'INVALID_ELEMENT_FIELD_TYPE', field: key, expected: 'array' });
96
- }
97
- }
98
- else {
99
- if (!isPlainObject(value)) {
100
- issues.push({ code: 'INVALID_ELEMENT_FIELD_TYPE', field: key, expected: 'object' });
101
- continue;
102
- }
103
- for (const numericKey of rule.numericKeys) {
104
- const inner = value[numericKey];
105
- if (inner !== undefined && inner !== null && typeof inner !== 'number') {
106
- issues.push({ code: 'INVALID_ELEMENT_FIELD_TYPE', field: `${key}.${numericKey}`, expected: 'number' });
107
- }
108
- }
109
- const unknownInner = Object.keys(value).filter((innerKey) => !rule.numericKeys.includes(innerKey));
110
- for (const innerKey of unknownInner) {
111
- issues.push({ code: 'UNKNOWN_ELEMENT_FIELD', field: `${key}.${innerKey}` });
112
- }
113
- }
114
- }
115
- return issues;
116
- }
117
- const UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
118
- function validateOperation(operation, index, options) {
119
- const action = operation === null || operation === void 0 ? void 0 : operation.action;
120
- if (typeof action !== 'string' || !KNOWN_OPERATION_ACTIONS.includes(action)) {
121
- return [{ code: 'UNKNOWN_OPERATION_ACTION', index, action: typeof action === 'string' ? action : undefined }];
122
- }
123
- if (action === 'deleteElement') {
124
- const elementId = operation.elementId;
125
- if (typeof elementId !== 'string' || elementId.length === 0) {
126
- return [{ code: 'OPERATION_MISSING_ELEMENT_ID', index, action }];
127
- }
128
- return [];
129
- }
130
- if (action === 'updateElement') {
131
- const elementId = operation.elementId;
132
- if (typeof elementId !== 'string' || elementId.length === 0) {
133
- return [{ code: 'OPERATION_MISSING_ELEMENT_ID', index, action }];
134
- }
135
- const changes = operation.changes;
136
- if (!isPlainObject(changes)) {
137
- return [{ code: 'OPERATION_MISSING_ELEMENT', index, action }];
138
- }
139
- return collectElementFieldIssues(changes, []).map((issue) => (Object.assign(Object.assign({}, issue), { index, action })));
140
- }
141
- const element = operation.element;
142
- if (!isPlainObject(element) || typeof element.id !== 'string' || element.id.length === 0) {
143
- return [{ code: 'OPERATION_MISSING_ELEMENT', index, action }];
144
- }
145
- const issues = collectElementFieldIssues(element, ['id', 'documentId']).map((issue) => (Object.assign(Object.assign({}, issue), { index, action })));
146
- const elementDocumentId = element.documentId;
147
- if (options.documentId !== undefined &&
148
- typeof elementDocumentId === 'string' &&
149
- elementDocumentId !== options.documentId) {
150
- issues.push({
151
- code: 'ELEMENT_DOCUMENT_ID_MISMATCH',
152
- index,
153
- action,
154
- elementDocumentId,
155
- documentId: options.documentId,
156
- });
157
- }
158
- return issues;
159
- }
160
- function validateWriteTransaction(request, options = {}) {
161
- const issues = [];
162
- const operations = request === null || request === void 0 ? void 0 : request.operations;
163
- if (!Array.isArray(operations) || operations.length === 0) {
164
- issues.push({ code: 'OPERATIONS_REQUIRED' });
165
- }
166
- else {
167
- operations.forEach((operation, index) => issues.push(...validateOperation(operation, index, options)));
168
- }
169
- const clientTransactionId = request === null || request === void 0 ? void 0 : request.clientTransactionId;
170
- if (clientTransactionId !== undefined &&
171
- (typeof clientTransactionId !== 'string' || !UUID_PATTERN.test(clientTransactionId))) {
172
- issues.push({ code: 'INVALID_CLIENT_TRANSACTION_ID' });
173
- }
174
- return issues.sort((a, b) => { var _a, _b; return CODE_RANK[a.code] - CODE_RANK[b.code] || ((_a = a.index) !== null && _a !== void 0 ? _a : -1) - ((_b = b.index) !== null && _b !== void 0 ? _b : -1); });
175
- }