@arcforges/operator-client 1.0.0-ci.101.1
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/LICENSE +202 -0
- package/NOTICE +63 -0
- package/README.md +5 -0
- package/build-identity.json +123 -0
- package/contracts.binpb +0 -0
- package/dist/gen/arcforges/operator/v1/operator_pb.d.ts +42 -0
- package/dist/gen/arcforges/operator/v1/operator_pb.js +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +4 -0
- package/dist/shapes/gen/proto.d.ts +2 -0
- package/dist/shapes/gen/proto.js +583 -0
- package/package.json +48 -0
- package/sbom.cdx.json +64 -0
- package/schemas/internal/proto/arcforges/operator/v1/operator.proto +20 -0
- package/schemas/public/proto/arcforges/events/v1/events.proto +14 -0
- package/schemas/public/proto/arcforges/foundation/v1/foundation.proto +248 -0
- package/schemas/public/proto/arcforges/hello/v1/hello.proto +23 -0
- package/schemas/public/proto/arcforges/publicapi/v1/content.proto +1200 -0
- package/source.json +36 -0
|
@@ -0,0 +1,583 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// <auto-generated />
|
|
3
|
+
// Generated by eng/generate_shapes.py; do not edit.
|
|
4
|
+
export function isId(input) { return checkId(input, { active: new Set(), depth: 0 }); }
|
|
5
|
+
function checkId(input, context) {
|
|
6
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input) || context.depth >= 100 || context.active.has(input))
|
|
7
|
+
return false;
|
|
8
|
+
context.active.add(input);
|
|
9
|
+
context.depth++;
|
|
10
|
+
try {
|
|
11
|
+
const value = input;
|
|
12
|
+
if (value.value === undefined)
|
|
13
|
+
return false;
|
|
14
|
+
if (value.value !== undefined) {
|
|
15
|
+
const fieldValue = value.value;
|
|
16
|
+
if (!(fieldValue instanceof Uint8Array))
|
|
17
|
+
return false;
|
|
18
|
+
if (fieldValue.length !== 16)
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
if (!value.value.some(v => v !== 0))
|
|
22
|
+
return false;
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
finally {
|
|
26
|
+
context.depth--;
|
|
27
|
+
context.active.delete(input);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function isOperatorCallContext(input) { return checkOperatorCallContext(input, { active: new Set(), depth: 0 }); }
|
|
31
|
+
function checkOperatorCallContext(input, context) {
|
|
32
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input) || context.depth >= 100 || context.active.has(input))
|
|
33
|
+
return false;
|
|
34
|
+
context.active.add(input);
|
|
35
|
+
context.depth++;
|
|
36
|
+
try {
|
|
37
|
+
const value = input;
|
|
38
|
+
if (value.context?.case === "caseId") {
|
|
39
|
+
const fieldValue = value.context.value;
|
|
40
|
+
if (!checkId(fieldValue, context))
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
if (value.context?.case === "incidentId") {
|
|
44
|
+
const fieldValue = value.context.value;
|
|
45
|
+
if (!checkId(fieldValue, context))
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
if (value.purpose === undefined)
|
|
49
|
+
return false;
|
|
50
|
+
if (value.purpose !== undefined) {
|
|
51
|
+
const fieldValue = value.purpose;
|
|
52
|
+
if (typeof fieldValue !== "string")
|
|
53
|
+
return false;
|
|
54
|
+
if (!validUnicode(fieldValue))
|
|
55
|
+
return false;
|
|
56
|
+
if ([...fieldValue].length < 1)
|
|
57
|
+
return false;
|
|
58
|
+
if (utf8Length(fieldValue) > 262144)
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
if (value.context === undefined || typeof value.context !== 'object' || value.context === null)
|
|
62
|
+
return false;
|
|
63
|
+
if (value.context.case !== "caseId" && value.context.case !== "incidentId")
|
|
64
|
+
return false;
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
context.depth--;
|
|
69
|
+
context.active.delete(input);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function validUnicode(text) {
|
|
73
|
+
for (let i = 0; i < text.length; i++) {
|
|
74
|
+
const unit = text.charCodeAt(i);
|
|
75
|
+
if (unit < 0xd800 || unit > 0xdfff)
|
|
76
|
+
continue;
|
|
77
|
+
if (unit > 0xdbff || ++i >= text.length)
|
|
78
|
+
return false;
|
|
79
|
+
const low = text.charCodeAt(i);
|
|
80
|
+
if (low < 0xdc00 || low > 0xdfff)
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
85
|
+
function canonicalDecimal(value) {
|
|
86
|
+
if (/^-?(0|[1-9][0-9]*)(\.[0-9]{1,9})?$/.exec(value)?.[0] !== value)
|
|
87
|
+
return false;
|
|
88
|
+
if (value.startsWith('-') && !/[1-9]/.test(value))
|
|
89
|
+
return false;
|
|
90
|
+
return value.replace(/[-.]/g, '').replace(/^0+/, '').length <= 28;
|
|
91
|
+
}
|
|
92
|
+
function utf8Length(value) {
|
|
93
|
+
let size = 0;
|
|
94
|
+
for (const scalar of value) {
|
|
95
|
+
const point = scalar.codePointAt(0);
|
|
96
|
+
size += point <= 0x7f ? 1 : point <= 0x7ff ? 2 : point <= 0xffff ? 3 : 4;
|
|
97
|
+
}
|
|
98
|
+
return size;
|
|
99
|
+
}
|
|
100
|
+
function reduced(numerator, denominator) {
|
|
101
|
+
if (denominator === 0n)
|
|
102
|
+
return false;
|
|
103
|
+
let a = numerator < 0n ? -numerator : numerator;
|
|
104
|
+
let b = denominator;
|
|
105
|
+
while (b !== 0n) {
|
|
106
|
+
const r = a % b;
|
|
107
|
+
a = b;
|
|
108
|
+
b = r;
|
|
109
|
+
}
|
|
110
|
+
return a === 1n;
|
|
111
|
+
}
|
|
112
|
+
function safeLink(value) {
|
|
113
|
+
const mailto = value.startsWith('mailto:');
|
|
114
|
+
const start = mailto ? 7 : value.startsWith('https://') ? 8 : value.startsWith('http://') ? 7 : -1;
|
|
115
|
+
if (start < 0 || value.length <= start || (!mailto && '/?#'.includes(value[start])))
|
|
116
|
+
return false;
|
|
117
|
+
// ECMAScript whitespace plus NEL equals C# Unicode whitespace plus BOM.
|
|
118
|
+
// This single-character search is linear; no authority/path backtracking.
|
|
119
|
+
return !/[\s\u0085]/u.test(value);
|
|
120
|
+
}
|
|
121
|
+
function idKey(value) { return Array.from(value.value, x => x.toString(16).padStart(2, '0')).join(''); }
|
|
122
|
+
function uniqueIds(values) { return new Set(values.map(idKey)).size === values.length; }
|
|
123
|
+
function orderedKeys(values) { return values.every((v, i) => i === 0 || values[i - 1] < v); }
|
|
124
|
+
function orderedIds(values) { return orderedKeys(values.map(idKey)); }
|
|
125
|
+
function compareInstant(a, b) { return a.unixSeconds < b.unixSeconds ? -1 : a.unixSeconds > b.unixSeconds ? 1 : Math.sign(a.nanos - b.nanos); }
|
|
126
|
+
function mediaRangeSemantics(value) {
|
|
127
|
+
return value.duration.ticks >= 0n && value.start.rate.numerator === value.duration.rate.numerator && value.start.rate.denominator === value.duration.rate.denominator && value.start.ticks + value.duration.ticks <= 9223372036854775807n;
|
|
128
|
+
}
|
|
129
|
+
function originSemantics(value) {
|
|
130
|
+
const kinds = ['aiGenerated', 'aiManipulated', 'nonAi', 'unknown'];
|
|
131
|
+
const positions = (value.kinds ?? []).map((k) => kinds.indexOf(k));
|
|
132
|
+
const parents = (value.parentOriginIds ?? []);
|
|
133
|
+
return positions.length > 0 && positions.every((v, i) => v >= 0 && (i === 0 || positions[i - 1] < v)) && orderedIds(parents) && (value.omittedParentCount === 0 || parents.length === 32) && parents.every(v => idKey(v) !== idKey(value.originId));
|
|
134
|
+
}
|
|
135
|
+
function resourceVersionSemantics(value) {
|
|
136
|
+
return !(value.revision.case === 'cloud' && value.revision.value.value <= 0n) && (value.blob === undefined || (value.contentHash !== undefined && value.contentHash === value.blob.contentHash));
|
|
137
|
+
}
|
|
138
|
+
const errorCategories = {
|
|
139
|
+
'validation.invalid_request': 1, 'validation.ast_bounds_exceeded': 1, 'validation.unsupported_version': 1, 'validation.invalid_offset': 1, 'media.time_not_representable': 1,
|
|
140
|
+
'auth.unauthenticated': 2, 'auth.session_expired': 2, 'auth.step_up_required': 2,
|
|
141
|
+
'auth.local_presence_required': 3, 'perm.capability_denied': 3, 'perm.resource_denied': 3, 'perm.egress_denied': 3, 'perm.approval_required': 3, 'perm.approval_expired': 3, 'perm.lease_expired': 3,
|
|
142
|
+
'entitlement.no_service_term': 4, 'entitlement.not_entitled': 4, 'entitlement.quota_exceeded': 4, 'entitlement.capacity_exhausted': 4, 'entitlement.extra_credits_required': 4, 'entitlement.credits_exhausted': 4, 'entitlement.request_too_large': 4, 'commerce.supplier_budget_exhausted': 4,
|
|
143
|
+
'conflict.revision_mismatch': 5, 'conflict.local_changes_pending': 5, 'conflict.duplicate_identifier': 5, 'command.reused_identifier': 5,
|
|
144
|
+
'state.not_found': 6, 'state.invalid_transition': 6, 'state.gone': 6, 'state.stale_fence': 6, 'sync.cursor_expired': 6, 'sync.bootstrap_expired': 6, 'identity.last_credential': 6,
|
|
145
|
+
'resource.unavailable': 7, 'resource.integrity_failed': 7, 'resource.upload_expired': 7, 'resource.parser_failed': 7, 'capacity.rate_limited': 7, 'capacity.busy': 7,
|
|
146
|
+
'dependency.unavailable': 8, 'dependency.timeout': 8, 'provider.declined': 8, 'security.isolation_unavailable': 8, 'internal.unexpected': 9,
|
|
147
|
+
};
|
|
148
|
+
const noRetryCodes = new Set(['auth.unauthenticated', 'auth.session_expired', 'auth.step_up_required', 'auth.local_presence_required', 'perm.capability_denied', 'perm.resource_denied', 'perm.egress_denied', 'perm.approval_required', 'perm.approval_expired', 'perm.lease_expired', 'entitlement.no_service_term', 'entitlement.not_entitled', 'entitlement.extra_credits_required', 'entitlement.credits_exhausted', 'validation.invalid_request', 'validation.ast_bounds_exceeded', 'validation.unsupported_version', 'identity.last_credential', 'conflict.duplicate_identifier', 'command.reused_identifier', 'state.not_found', 'state.invalid_transition', 'state.gone', 'resource.integrity_failed']);
|
|
149
|
+
function errorSemantics(value) {
|
|
150
|
+
const category = Object.hasOwn(errorCategories, value.code) ? errorCategories[value.code] : undefined;
|
|
151
|
+
if (category !== undefined && value.category !== category)
|
|
152
|
+
return false;
|
|
153
|
+
if (category !== undefined && !['dependency.unavailable', 'dependency.timeout', 'internal.unexpected', 'resource.parser_failed'].includes(value.code) && value.effect !== 1)
|
|
154
|
+
return false;
|
|
155
|
+
if (value.code === 'dependency.timeout' && value.effect !== 3)
|
|
156
|
+
return false;
|
|
157
|
+
if (['entitlement.capacity_exhausted', 'capacity.rate_limited', 'capacity.busy'].includes(value.code) && value.retry.mode !== 3)
|
|
158
|
+
return false;
|
|
159
|
+
if (noRetryCodes.has(value.code) && value.retry.mode !== 1)
|
|
160
|
+
return false;
|
|
161
|
+
return !(value.effect === 3 && value.retry.mode === 3);
|
|
162
|
+
}
|
|
163
|
+
function validDate(value) {
|
|
164
|
+
if (/^\d{4}-\d{2}-\d{2}$/.exec(value)?.[0] !== value)
|
|
165
|
+
return false;
|
|
166
|
+
const year = Number(value.slice(0, 4)), month = Number(value.slice(5, 7)), day = Number(value.slice(8, 10));
|
|
167
|
+
if (year < 1 || month < 1 || month > 12)
|
|
168
|
+
return false;
|
|
169
|
+
const leap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
170
|
+
return day >= 1 && day <= [31, leap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month - 1];
|
|
171
|
+
}
|
|
172
|
+
function scalarSemantics(value) {
|
|
173
|
+
const scalar = value.value;
|
|
174
|
+
switch (scalar.case) {
|
|
175
|
+
case 'null': return scalar.value === true;
|
|
176
|
+
case 'number': return !scalar.value.value.includes('.') || !scalar.value.value.endsWith('0');
|
|
177
|
+
case 'date': return validDate(scalar.value);
|
|
178
|
+
case 'multiSelect': return (scalar.value.items ?? []).length <= 100 && orderedIds(scalar.value.items ?? []);
|
|
179
|
+
case 'dateTime': return scalar.value.nanos % 100 === 0;
|
|
180
|
+
default: return true;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function predicateSemantics(value) {
|
|
184
|
+
const operands = (value.operands ?? []);
|
|
185
|
+
if (['isMissing', 'isPresent'].includes(value.operator))
|
|
186
|
+
return operands.length === 0;
|
|
187
|
+
const membership = ['in', 'hasAny', 'hasAll'].includes(value.operator);
|
|
188
|
+
if (membership ? operands.length < 1 || operands.length > 100 : operands.length !== 1)
|
|
189
|
+
return false;
|
|
190
|
+
const kind = operands[0].value.case;
|
|
191
|
+
if (kind === 'null' || operands.some(v => v.value.case !== kind))
|
|
192
|
+
return false;
|
|
193
|
+
if (operands.some(v => ['text', 'url'].includes(v.value.case) && [...v.value.value].length > 4096))
|
|
194
|
+
return false;
|
|
195
|
+
if (['hasAny', 'hasAll'].includes(value.operator))
|
|
196
|
+
return kind === 'select';
|
|
197
|
+
if (['contains', 'startsWith', 'endsWith'].includes(value.operator))
|
|
198
|
+
return ['text', 'url'].includes(kind);
|
|
199
|
+
if (['eq', 'ne'].includes(value.operator))
|
|
200
|
+
return true;
|
|
201
|
+
return kind !== 'multiSelect' && ['lt', 'le', 'gt', 'ge', 'in'].includes(value.operator);
|
|
202
|
+
}
|
|
203
|
+
function filterBounds(root) {
|
|
204
|
+
const pending = [[root, 1]];
|
|
205
|
+
let count = 0;
|
|
206
|
+
while (pending.length) {
|
|
207
|
+
const [node, depth] = pending.pop();
|
|
208
|
+
if (++count > 128 || depth > 8)
|
|
209
|
+
return false;
|
|
210
|
+
if (node.expression.case === 'group')
|
|
211
|
+
for (const child of node.expression.value.children ?? [])
|
|
212
|
+
pending.push([child, depth + 1]);
|
|
213
|
+
}
|
|
214
|
+
return true;
|
|
215
|
+
}
|
|
216
|
+
function querySemantics(value) {
|
|
217
|
+
if ((value.savedViewId === undefined) !== (value.savedViewRev === undefined) || (value.savedViewRev !== undefined && value.savedViewRev.value <= 0n))
|
|
218
|
+
return false;
|
|
219
|
+
const projection = (value.projection ?? []), sorts = (value.sorts ?? []), versions = (value.definitionVersions ?? []);
|
|
220
|
+
if (!uniqueIds(projection) || !uniqueIds(sorts.map(v => v.propertyId)) || !uniqueIds(versions.map(v => v.propertyId)))
|
|
221
|
+
return false;
|
|
222
|
+
const definitions = new Set(versions.map(v => idKey(v.propertyId)));
|
|
223
|
+
if (versions.some(v => v.semanticRevision.value <= 0n) || projection.some(v => !definitions.has(idKey(v))) || sorts.some(v => !definitions.has(idKey(v.propertyId))))
|
|
224
|
+
return false;
|
|
225
|
+
const pending = value.filter === undefined ? [] : [value.filter];
|
|
226
|
+
let count = 0;
|
|
227
|
+
while (pending.length) {
|
|
228
|
+
const node = pending.pop();
|
|
229
|
+
if (++count > 128)
|
|
230
|
+
return false;
|
|
231
|
+
if (node.expression.case === 'predicate' && !definitions.has(idKey(node.expression.value.propertyId)))
|
|
232
|
+
return false;
|
|
233
|
+
if (node.expression.case === 'group')
|
|
234
|
+
pending.push(...node.expression.value.children ?? []);
|
|
235
|
+
}
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
function definitionSemantics(value) {
|
|
239
|
+
const options = (value.options ?? []);
|
|
240
|
+
return value.semanticRevision.value > 0n && value.revision.value > 0n && (value.numberScale === undefined || value.type === 'number') && (['select', 'multiSelect'].includes(value.type) || options.length === 0) && uniqueIds(options.map(v => v.optionId)) && new Set(options.map(v => v.order)).size === options.length;
|
|
241
|
+
}
|
|
242
|
+
function savedViewSemantics(value) {
|
|
243
|
+
return value.query.page.cursor === undefined && value.query.datasetToken === undefined && value.query.savedViewId === undefined && value.query.savedViewRev === undefined && idKey(value.notebookId) === idKey(value.query.notebookId);
|
|
244
|
+
}
|
|
245
|
+
function structuredBounds(root) {
|
|
246
|
+
const pending = [[root, 1]];
|
|
247
|
+
while (pending.length) {
|
|
248
|
+
const [node, depth] = pending.pop();
|
|
249
|
+
if (depth > 16)
|
|
250
|
+
return false;
|
|
251
|
+
if (node.value.case === 'null' && node.value.value !== true)
|
|
252
|
+
return false;
|
|
253
|
+
if (node.value.case === 'list')
|
|
254
|
+
for (const child of node.value.value.items ?? [])
|
|
255
|
+
pending.push([child, depth + 1]);
|
|
256
|
+
if (node.value.case === 'record')
|
|
257
|
+
for (const entry of node.value.value.entries ?? [])
|
|
258
|
+
pending.push([entry.value, depth + 1]);
|
|
259
|
+
}
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
function tableSemantics(value) {
|
|
263
|
+
const rows = (value.rows ?? []);
|
|
264
|
+
if (!rows.length)
|
|
265
|
+
return false;
|
|
266
|
+
const width = (rows[0].cells ?? []).length;
|
|
267
|
+
return width >= 1 && width <= 50 && rows.every(v => (v.cells ?? []).length === width) && uniqueIds(rows.map(v => v.rowId)) && uniqueIds(rows.flatMap(v => (v.cells ?? []).map((c) => c.cellId)));
|
|
268
|
+
}
|
|
269
|
+
function boundary(text, offset) { return offset <= text.length && (offset === 0 || offset === text.length || text.charCodeAt(offset) < 0xdc00 || text.charCodeAt(offset) > 0xdfff); }
|
|
270
|
+
function richTextSemantics(value) {
|
|
271
|
+
const text = value.text, runs = (value.runs ?? []), atoms = (value.atoms ?? []), spans = (value.spans ?? []);
|
|
272
|
+
if (text.normalize('NFC') !== text)
|
|
273
|
+
return false;
|
|
274
|
+
if (!text.length)
|
|
275
|
+
return runs.length === 1 && runs[0].from === 0 && runs[0].until === 0 && atoms.length === 0 && spans.length === 0;
|
|
276
|
+
if (!uniqueIds([...runs.map(v => v.runId), ...atoms.map(v => v.inlineId)]))
|
|
277
|
+
return false;
|
|
278
|
+
const intervals = [];
|
|
279
|
+
for (const run of runs) {
|
|
280
|
+
if (run.from >= run.until || !boundary(text, run.from) || !boundary(text, run.until) || text.slice(run.from, run.until).includes('\uFFFC'))
|
|
281
|
+
return false;
|
|
282
|
+
intervals.push([run.from, run.until]);
|
|
283
|
+
}
|
|
284
|
+
for (const atom of atoms) {
|
|
285
|
+
if (atom.offset >= text.length || text[atom.offset] !== '\uFFFC' || (atom.content.case === 'math' && atom.content.value.display))
|
|
286
|
+
return false;
|
|
287
|
+
intervals.push([atom.offset, atom.offset + 1]);
|
|
288
|
+
}
|
|
289
|
+
intervals.sort((a, b) => a[0] - b[0]);
|
|
290
|
+
let end = 0;
|
|
291
|
+
for (const interval of intervals) {
|
|
292
|
+
if (interval[0] !== end)
|
|
293
|
+
return false;
|
|
294
|
+
end = interval[1];
|
|
295
|
+
}
|
|
296
|
+
if (end !== text.length)
|
|
297
|
+
return false;
|
|
298
|
+
let spanEnd = 0;
|
|
299
|
+
for (const span of spans) {
|
|
300
|
+
if (span.from >= span.until || span.from < spanEnd || !boundary(text, span.from) || !boundary(text, span.until) || new Set(span.marks ?? []).size !== (span.marks ?? []).length)
|
|
301
|
+
return false;
|
|
302
|
+
spanEnd = span.until;
|
|
303
|
+
}
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
function blockSemantics(value) {
|
|
307
|
+
const expected = { paragraph: 'text', heading: 'text', list: 'text', quote: 'text', callout: 'text', toggle: 'text', code: 'code', image: 'resource', attachment: 'resource', embed: 'link', table: 'table', math: 'math', divider: 'empty' };
|
|
308
|
+
const body = value.body.content;
|
|
309
|
+
if (expected[value.kind] === undefined || body.case !== expected[value.kind] || (body.case === 'empty' && body.value !== true) || (body.case === 'math' && body.value.display !== true))
|
|
310
|
+
return false;
|
|
311
|
+
const p = value.properties;
|
|
312
|
+
if (p === undefined)
|
|
313
|
+
return !['heading', 'list', 'callout', 'image', 'attachment', 'embed'].includes(value.kind);
|
|
314
|
+
if ((p.headingLevel !== undefined) !== (value.kind === 'heading') || (p.listStyle !== undefined) !== (value.kind === 'list') || (p.calloutKind !== undefined) !== (value.kind === 'callout') || (p.altText !== undefined) !== (value.kind === 'image') || (p.imageLayout !== undefined) !== (value.kind === 'image') || (p.attachmentPresentation !== undefined) !== (value.kind === 'attachment') || (p.embedRenderMode !== undefined) !== (value.kind === 'embed'))
|
|
315
|
+
return false;
|
|
316
|
+
return (p.checked !== undefined) === (value.kind === 'list' && p.listStyle === 'checklist');
|
|
317
|
+
}
|
|
318
|
+
function documentSemantics(value) {
|
|
319
|
+
const rows = (value.blocks ?? []), properties = (value.properties ?? []);
|
|
320
|
+
if (!uniqueIds(rows.map(v => v.blockId)) || !uniqueIds(properties.map(v => v.propertyId)) || !uniqueIds(value.tags ?? []))
|
|
321
|
+
return false;
|
|
322
|
+
const blocks = new Map(rows.map(v => [idKey(v.blockId), v])), positions = new Set();
|
|
323
|
+
for (const block of rows) {
|
|
324
|
+
const position = (block.parentId === undefined ? 'root' : idKey(block.parentId)) + ':' + block.orderKey;
|
|
325
|
+
if (positions.has(position))
|
|
326
|
+
return false;
|
|
327
|
+
positions.add(position);
|
|
328
|
+
const seen = new Set([idKey(block.blockId)]);
|
|
329
|
+
let parent = block.parentId;
|
|
330
|
+
while (parent !== undefined) {
|
|
331
|
+
const key = idKey(parent), parentBlock = blocks.get(key);
|
|
332
|
+
if (seen.has(key) || parentBlock === undefined)
|
|
333
|
+
return false;
|
|
334
|
+
seen.add(key);
|
|
335
|
+
parent = parentBlock.parentId;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return true;
|
|
339
|
+
}
|
|
340
|
+
function compareScopeTime(a, b) {
|
|
341
|
+
const left = a.ticks * a.rate.denominator * b.rate.numerator;
|
|
342
|
+
const right = b.ticks * b.rate.denominator * a.rate.numerator;
|
|
343
|
+
return left < right ? -1 : left > right ? 1 : 0;
|
|
344
|
+
}
|
|
345
|
+
function alignmentSemantics(value) {
|
|
346
|
+
const left = value.leftAnchor !== undefined, right = value.rightAnchor !== undefined, offset = value.offset !== undefined, event = value.eventId !== undefined;
|
|
347
|
+
switch (value.kind) {
|
|
348
|
+
case 'absoluteTime': return !left && !right && !offset && !event;
|
|
349
|
+
case 'trigger': return left && right && !offset && !event;
|
|
350
|
+
case 'event': return left && right && !offset && event;
|
|
351
|
+
case 'manualOffset': return !left && !right && offset && !event;
|
|
352
|
+
default: return false;
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
function cursorSemantics(value) {
|
|
356
|
+
const a = value.a.time, b = value.b.time, d = value.deltaTime;
|
|
357
|
+
const left = d.ticks * d.rate.denominator * a.rate.numerator * b.rate.numerator;
|
|
358
|
+
const right = (b.ticks * b.rate.denominator * a.rate.numerator - a.ticks * a.rate.denominator * b.rate.numerator) * d.rate.numerator;
|
|
359
|
+
const expected = value.b.value - value.a.value;
|
|
360
|
+
return left === right && Number.isFinite(expected) && Math.abs(value.deltaValue - expected) <= 1e-12 + 1e-9 * Math.abs(expected);
|
|
361
|
+
}
|
|
362
|
+
function configurationSemantics(value) {
|
|
363
|
+
const rows = (value.channels ?? []);
|
|
364
|
+
if (!uniqueIds(rows.map(v => v.channelId)))
|
|
365
|
+
return false;
|
|
366
|
+
const channels = new Set(rows.map(v => idKey(v.channelId)));
|
|
367
|
+
if ((value.framing.fields ?? []).some((v) => !channels.has(idKey(v.channelId))))
|
|
368
|
+
return false;
|
|
369
|
+
return value.trigger?.channelId === undefined || channels.has(idKey(value.trigger.channelId));
|
|
370
|
+
}
|
|
371
|
+
function frameSemantics(value) {
|
|
372
|
+
const fields = (value.fields ?? []);
|
|
373
|
+
if (!uniqueIds(fields.map(v => v.channelId)))
|
|
374
|
+
return false;
|
|
375
|
+
const start = value.start, end = value.end;
|
|
376
|
+
const newline = end.length === 1 && end[0] === 10 || end.length === 2 && end[0] === 13 && end[1] === 10;
|
|
377
|
+
switch (value.kind) {
|
|
378
|
+
case 'delimitedText': return start.length <= 16 && end.length >= 1 && end.length <= 16 && value.delimiter === undefined && value.frameBytes === undefined && !value.header && fields.every(v => v.offset === undefined && (v.jsonPath ?? []).length === 0);
|
|
379
|
+
case 'csvLine': return start.length === 0 && newline && value.escapeByte === undefined && [44, 59, 9].includes(value.delimiter) && value.frameBytes === undefined && fields.every(v => v.column !== undefined && v.offset === undefined && (v.jsonPath ?? []).length === 0);
|
|
380
|
+
case 'jsonLine': return start.length === 0 && newline && value.escapeByte === undefined && value.delimiter === undefined && value.frameBytes === undefined && !value.header && fields.every(v => v.column === undefined && v.offset === undefined && (v.jsonPath ?? []).length !== 0);
|
|
381
|
+
case 'canonicalReplay': return start.length === 0 && end.length === 0 && value.escapeByte === undefined && value.delimiter === undefined && value.frameBytes === undefined && !value.header && fields.length === 0 && value.checksum === undefined;
|
|
382
|
+
case 'fixedBinary': {
|
|
383
|
+
if (start.length || end.length || value.escapeByte !== undefined || value.delimiter !== undefined || value.header || value.frameBytes === undefined || value.frameBytes < 1 || value.frameBytes > 1048576 || !['little', 'big'].includes(value.byteOrder))
|
|
384
|
+
return false;
|
|
385
|
+
const widths = { u8: 1, i8: 1, bool: 1, u16: 2, i16: 2, u32: 4, i32: 4, f32: 4, u64: 8, i64: 8, f64: 8 };
|
|
386
|
+
const intervals = [];
|
|
387
|
+
for (const field of fields) {
|
|
388
|
+
const width = widths[field.scalarType];
|
|
389
|
+
if (width === undefined || field.offset === undefined || field.column !== undefined || (field.jsonPath ?? []).length || field.offset + width > value.frameBytes)
|
|
390
|
+
return false;
|
|
391
|
+
const end = field.offset + width;
|
|
392
|
+
if (intervals.some(([from, until]) => field.offset < until && from < end))
|
|
393
|
+
return false;
|
|
394
|
+
intervals.push([field.offset, end]);
|
|
395
|
+
}
|
|
396
|
+
if (value.checksum !== undefined) {
|
|
397
|
+
const checksumWidths = { xor8: 1, crc16CcittFalse: 2, crc32IsoHdlc: 4 };
|
|
398
|
+
const checksum = value.checksum, width = checksumWidths[checksum.algorithm];
|
|
399
|
+
if (width === undefined || checksum.offset + width > value.frameBytes || checksum.input.offset + checksum.input.length > BigInt(value.frameBytes))
|
|
400
|
+
return false;
|
|
401
|
+
}
|
|
402
|
+
return true;
|
|
403
|
+
}
|
|
404
|
+
default: return false;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function checksumSemantics(value) {
|
|
408
|
+
const widths = { xor8: 1n, crc16CcittFalse: 2n, crc32IsoHdlc: 4n };
|
|
409
|
+
const width = widths[value.algorithm];
|
|
410
|
+
return width !== undefined && ['little', 'big'].includes(value.byteOrder) &&
|
|
411
|
+
(value.input.offset + value.input.length <= BigInt(value.offset) || BigInt(value.offset) + width <= value.input.offset);
|
|
412
|
+
}
|
|
413
|
+
function triggerSemantics(value) {
|
|
414
|
+
if (value.hysteresis < 0 || value.holdoff.ticks < 0n || value.pre.ticks < 0n || value.post.ticks < 0n || value.maxOccurrences === 0 || (!value.repeated && value.maxOccurrences !== 1))
|
|
415
|
+
return false;
|
|
416
|
+
return value.kind === 'manual' ? value.channelId === undefined && value.threshold === undefined && value.direction === undefined && value.hysteresis === 0 : value.kind === 'edge' && value.channelId !== undefined && value.threshold !== undefined && ['rising', 'falling', 'either'].includes(value.direction);
|
|
417
|
+
}
|
|
418
|
+
function pulseFamily(family) { return ['frequency', 'dutyCycle', 'riseTime', 'fallTime'].includes(family); }
|
|
419
|
+
function thresholdSemantics(value) {
|
|
420
|
+
if (!pulseFamily(value.family))
|
|
421
|
+
return false;
|
|
422
|
+
switch (value.name) {
|
|
423
|
+
case 'low':
|
|
424
|
+
case 'high': return true;
|
|
425
|
+
case 'fraction10': return value.unit === '1' && value.value === 0.1;
|
|
426
|
+
case 'fraction50': return value.unit === '1' && value.value === 0.5;
|
|
427
|
+
case 'fraction90': return value.unit === '1' && value.value === 0.9;
|
|
428
|
+
default: return false;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
function fixedUnit(name) {
|
|
432
|
+
if (['count', 'eventCount', 'dutyCycle'].includes(name))
|
|
433
|
+
return '1';
|
|
434
|
+
if (['duration', 'riseTime', 'fallTime', 'deltaTime'].includes(name))
|
|
435
|
+
return 's';
|
|
436
|
+
return name === 'frequency' ? 'Hz' : undefined;
|
|
437
|
+
}
|
|
438
|
+
function familySemantics(value) {
|
|
439
|
+
const values = (value.values ?? []);
|
|
440
|
+
if (value.status !== 'ok') {
|
|
441
|
+
if (values.length || value.reason === undefined)
|
|
442
|
+
return false;
|
|
443
|
+
if (value.status === 'invalid')
|
|
444
|
+
return ['invalidTimeOrder', 'invalidConfiguration', 'numericOverflow'].includes(value.reason);
|
|
445
|
+
if (value.status !== 'insufficient')
|
|
446
|
+
return false;
|
|
447
|
+
switch (value.reason) {
|
|
448
|
+
case 'noFiniteSamples': return !['count', 'duration', 'eventCount'].includes(value.family);
|
|
449
|
+
case 'noCompleteCycle': return ['frequency', 'dutyCycle'].includes(value.family);
|
|
450
|
+
case 'noCompleteEdge': return ['riseTime', 'fallTime'].includes(value.family);
|
|
451
|
+
case 'cursorUnavailable': return value.family === 'cursorDelta';
|
|
452
|
+
default: return false;
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
if (value.reason !== undefined)
|
|
456
|
+
return false;
|
|
457
|
+
if (value.validCount === 0n && ['minimum', 'maximum', 'mean', 'rms', 'peakToPeak', 'standardDeviation'].includes(value.family))
|
|
458
|
+
return false;
|
|
459
|
+
if (value.family === 'cursorDelta') {
|
|
460
|
+
if (values.length !== 2 || !values.some(v => v.name === 'deltaTime') || !values.some(v => v.name === 'deltaValue'))
|
|
461
|
+
return false;
|
|
462
|
+
}
|
|
463
|
+
else if (values.length !== 1 || values[0].name !== value.family)
|
|
464
|
+
return false;
|
|
465
|
+
for (const item of values) {
|
|
466
|
+
const unit = fixedUnit(item.name);
|
|
467
|
+
if (unit !== undefined && item.unit !== unit)
|
|
468
|
+
return false;
|
|
469
|
+
if (item.name === 'dutyCycle' && (item.result.value < 0 || item.result.value > 1))
|
|
470
|
+
return false;
|
|
471
|
+
if (['duration', 'frequency'].includes(item.name) && item.result.value <= 0)
|
|
472
|
+
return false;
|
|
473
|
+
if (['rms', 'peakToPeak', 'standardDeviation', 'riseTime', 'fallTime'].includes(item.name) && item.result.value < 0)
|
|
474
|
+
return false;
|
|
475
|
+
if (item.name === 'count' && item.result.value !== value.validCount)
|
|
476
|
+
return false;
|
|
477
|
+
}
|
|
478
|
+
return true;
|
|
479
|
+
}
|
|
480
|
+
function sourceSemantics(value, configuration) {
|
|
481
|
+
if (value.capture.contentHash === undefined || value.configuration.contentHash === undefined)
|
|
482
|
+
return false;
|
|
483
|
+
if ([value.decoder, value.timeMapping, value.eventSet].some(v => v !== undefined && v.contentHash === undefined))
|
|
484
|
+
return false;
|
|
485
|
+
if (value.configuration.revision.case === 'native' && value.configuration.revision.value.value !== configuration.revision.value)
|
|
486
|
+
return false;
|
|
487
|
+
return (configuration.channels ?? []).some((v) => idKey(v.channelId) === idKey(value.channelId));
|
|
488
|
+
}
|
|
489
|
+
function thresholdBindings(values, channels, families, result, levels, fractions) {
|
|
490
|
+
const resolved = new Map();
|
|
491
|
+
for (const threshold of values) {
|
|
492
|
+
if (!families.has(threshold.family) || (result && threshold.channelId === undefined))
|
|
493
|
+
return undefined;
|
|
494
|
+
const level = ['low', 'high'].includes(threshold.name);
|
|
495
|
+
if (level ? !levels : !fractions)
|
|
496
|
+
return undefined;
|
|
497
|
+
const targets = threshold.channelId === undefined ? [...channels].filter(([, channel]) => !level || channel.unit === threshold.unit).map(([key]) => key) : [idKey(threshold.channelId)];
|
|
498
|
+
if (!targets.length)
|
|
499
|
+
return undefined;
|
|
500
|
+
for (const target of targets) {
|
|
501
|
+
const channel = channels.get(target), key = target + ':' + threshold.family + ':' + threshold.name;
|
|
502
|
+
if (channel === undefined || (level && threshold.unit !== channel.unit) || resolved.has(key))
|
|
503
|
+
return undefined;
|
|
504
|
+
resolved.set(key, threshold);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
for (const [key, threshold] of resolved) {
|
|
508
|
+
if (!['low', 'high'].includes(threshold.name))
|
|
509
|
+
continue;
|
|
510
|
+
const prefix = key.slice(0, key.lastIndexOf(':') + 1), low = resolved.get(prefix + 'low'), high = resolved.get(prefix + 'high');
|
|
511
|
+
if (low === undefined || high === undefined || low.value >= high.value)
|
|
512
|
+
return undefined;
|
|
513
|
+
}
|
|
514
|
+
return resolved;
|
|
515
|
+
}
|
|
516
|
+
function measurementRequestSemantics(value) {
|
|
517
|
+
const ids = (value.channels ?? []), requested = (value.families ?? []), cursors = (value.cursors ?? []);
|
|
518
|
+
if (!ids.length || !uniqueIds(ids) || !requested.length || new Set(requested).size !== requested.length)
|
|
519
|
+
return false;
|
|
520
|
+
if (!sourceSemantics(value.source, value.configuration) || !ids.some(v => idKey(v) === idKey(value.source.channelId)))
|
|
521
|
+
return false;
|
|
522
|
+
if (value.source.capture.revision.case === 'native' && value.source.capture.revision.value.value !== value.sourceRevision.value)
|
|
523
|
+
return false;
|
|
524
|
+
const available = new Map((value.configuration.channels ?? []).map(v => [idKey(v.channelId), v])), channels = new Map();
|
|
525
|
+
for (const id of ids) {
|
|
526
|
+
const key = idKey(id), channel = available.get(key);
|
|
527
|
+
if (channel === undefined)
|
|
528
|
+
return false;
|
|
529
|
+
channels.set(key, channel);
|
|
530
|
+
}
|
|
531
|
+
const families = new Set(requested);
|
|
532
|
+
if (thresholdBindings(value.referenceLevels ?? [], channels, families, false, true, false) === undefined || thresholdBindings(value.thresholds ?? [], channels, families, false, false, true) === undefined)
|
|
533
|
+
return false;
|
|
534
|
+
if (families.has('cursorDelta') ? cursors.length !== 2 : cursors.length !== 0)
|
|
535
|
+
return false;
|
|
536
|
+
for (const cursor of cursors)
|
|
537
|
+
if (!channels.has(idKey(cursor.channelId)) || compareScopeTime(cursor.time, value.window.start) < 0 || compareScopeTime(cursor.time, value.window.end) >= 0)
|
|
538
|
+
return false;
|
|
539
|
+
return cursors.length !== 2 || channels.get(idKey(cursors[0].channelId)).unit === channels.get(idKey(cursors[1].channelId)).unit;
|
|
540
|
+
}
|
|
541
|
+
function measurementResultSemantics(value) {
|
|
542
|
+
if (!sourceSemantics(value.source, value.configuration) || value.runCount > value.finiteCount || value.requestedDuration.ticks <= 0n || value.coveredDuration.ticks < 0n || value.timingUncertainty.ticks < 0n || compareScopeTime(value.coveredDuration, value.requestedDuration) > 0)
|
|
543
|
+
return false;
|
|
544
|
+
if (value.finiteCount === 0n ? value.runCount !== 0n || value.coveredDuration.ticks !== 0n : value.runCount === 0n)
|
|
545
|
+
return false;
|
|
546
|
+
const channels = new Map((value.configuration.channels ?? []).map(v => [idKey(v.channelId), v])), pairs = new Set(), rows = (value.families ?? []), families = new Set(rows.map(v => v.family));
|
|
547
|
+
for (const family of rows) {
|
|
548
|
+
const channel = channels.get(idKey(family.channelId)), pair = idKey(family.channelId) + ':' + family.family;
|
|
549
|
+
if (channel === undefined || pairs.has(pair))
|
|
550
|
+
return false;
|
|
551
|
+
pairs.add(pair);
|
|
552
|
+
for (const item of (family.values ?? []))
|
|
553
|
+
if (fixedUnit(item.name) === undefined && item.unit !== channel.unit)
|
|
554
|
+
return false;
|
|
555
|
+
}
|
|
556
|
+
const resolved = thresholdBindings(value.resolvedThresholds ?? [], channels, families, true, true, true);
|
|
557
|
+
if (resolved === undefined || [...resolved.keys()].some(key => !pairs.has(key.slice(0, key.lastIndexOf(':')))))
|
|
558
|
+
return false;
|
|
559
|
+
for (const family of rows.filter(v => v.status === 'ok' && pulseFamily(v.family))) {
|
|
560
|
+
const prefix = idKey(family.channelId) + ':' + family.family + ':';
|
|
561
|
+
if (['low', 'high', 'fraction10', 'fraction50', 'fraction90'].some(name => !resolved.has(prefix + name)))
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
const cursorFamilies = rows.filter(v => v.family === 'cursorDelta' && v.status === 'ok');
|
|
565
|
+
if ((value.cursor !== undefined) !== (cursorFamilies.length !== 0))
|
|
566
|
+
return false;
|
|
567
|
+
if (value.cursor === undefined)
|
|
568
|
+
return true;
|
|
569
|
+
const left = channels.get(idKey(value.cursor.a.channelId)), right = channels.get(idKey(value.cursor.b.channelId));
|
|
570
|
+
if (left === undefined || right === undefined || left.unit !== right.unit)
|
|
571
|
+
return false;
|
|
572
|
+
const seconds = Number(value.cursor.deltaTime.ticks) * Number(value.cursor.deltaTime.rate.denominator) / Number(value.cursor.deltaTime.rate.numerator);
|
|
573
|
+
for (const family of cursorFamilies) {
|
|
574
|
+
if (channels.get(idKey(family.channelId)).unit !== left.unit)
|
|
575
|
+
return false;
|
|
576
|
+
for (const item of family.values) {
|
|
577
|
+
const expected = item.name === 'deltaTime' ? seconds : value.cursor.deltaValue;
|
|
578
|
+
if (Math.abs(item.result.value - expected) > 1e-12 + 1e-9 * Math.abs(expected))
|
|
579
|
+
return false;
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
return true;
|
|
583
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@arcforges/operator-client",
|
|
3
|
+
"version": "1.0.0-ci.101.1",
|
|
4
|
+
"description": "Internal operator protobuf records; Operations-only import boundary.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"sideEffects": false,
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/ArcForges/Contracts.git",
|
|
11
|
+
"directory": "src/internal/ts/operator-client"
|
|
12
|
+
},
|
|
13
|
+
"homepage": "https://github.com/ArcForges/Contracts#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/ArcForges/Contracts/issues"
|
|
16
|
+
},
|
|
17
|
+
"exports": {
|
|
18
|
+
".": {
|
|
19
|
+
"types": "./dist/index.d.ts",
|
|
20
|
+
"import": "./dist/index.js"
|
|
21
|
+
},
|
|
22
|
+
"./build-identity": "./build-identity.json"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"LICENSE",
|
|
26
|
+
"NOTICE",
|
|
27
|
+
"README.md",
|
|
28
|
+
"build-identity.json",
|
|
29
|
+
"contracts.binpb",
|
|
30
|
+
"dist",
|
|
31
|
+
"proto",
|
|
32
|
+
"sbom.cdx.json",
|
|
33
|
+
"schemas",
|
|
34
|
+
"source.json"
|
|
35
|
+
],
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@arcforges/proto": "1.0.0-ci.101.1",
|
|
38
|
+
"@bufbuild/protobuf": "2.15.0"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public",
|
|
42
|
+
"registry": "https://registry.npmjs.org/"
|
|
43
|
+
},
|
|
44
|
+
"arcforges": {
|
|
45
|
+
"licenceBoundary": "Apache",
|
|
46
|
+
"contractAccess": "internal"
|
|
47
|
+
}
|
|
48
|
+
}
|