@hyperscale0/udl 3.1.0 → 4.0.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.
- package/CHANGELOG.md +8 -0
- package/README.md +1 -1
- package/dist/diagnostics.d.ts +1 -1
- package/dist/diagnostics.d.ts.map +1 -1
- package/dist/diagnostics.js +13 -1
- package/dist/diagnostics.js.map +1 -1
- package/dist/evolution.d.ts.map +1 -1
- package/dist/evolution.js +5 -0
- package/dist/evolution.js.map +1 -1
- package/dist/finance.js +2 -1
- package/dist/finance.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/instrument-references.d.ts.map +1 -1
- package/dist/instrument-references.js +21 -1
- package/dist/instrument-references.js.map +1 -1
- package/dist/object-contract.d.ts +157 -0
- package/dist/object-contract.d.ts.map +1 -0
- package/dist/object-contract.js +306 -0
- package/dist/object-contract.js.map +1 -0
- package/dist/reporting-validation.d.ts +8 -0
- package/dist/reporting-validation.d.ts.map +1 -0
- package/dist/reporting-validation.js +245 -0
- package/dist/reporting-validation.js.map +1 -0
- package/dist/reporting.d.ts +478 -0
- package/dist/reporting.d.ts.map +1 -0
- package/dist/reporting.js +170 -0
- package/dist/reporting.js.map +1 -0
- package/dist/schema.d.ts +2933 -24
- package/dist/schema.d.ts.map +1 -1
- package/dist/schema.js +163 -23
- package/dist/schema.js.map +1 -1
- package/dist/validation.d.ts +5 -2
- package/dist/validation.d.ts.map +1 -1
- package/dist/validation.js +495 -124
- package/dist/validation.js.map +1 -1
- package/docs/README.md +87 -9
- package/package.json +4 -4
- package/spec/README.md +87 -9
- package/spec/{darb.udl.json → cars.udl.json} +7 -7
- package/spec/udl.schema.json +2969 -4558
- package/src/diagnostics.ts +33 -1
- package/src/evolution.ts +8 -0
- package/src/finance.ts +1 -1
- package/src/index.ts +9 -0
- package/src/instrument-references.ts +25 -1
- package/src/object-contract.ts +498 -0
- package/src/reporting-validation.ts +381 -0
- package/src/reporting.ts +179 -0
- package/src/schema.ts +219 -23
- package/src/validation.ts +765 -136
package/src/schema.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import * as z from "zod";
|
|
2
|
+
import { reportDefinitionSchema } from "./reporting.js";
|
|
2
3
|
|
|
3
|
-
export const UDL_FORMAT_VERSION =
|
|
4
|
+
export const UDL_FORMAT_VERSION = 4 as const;
|
|
5
|
+
/** Counts the root and every nested invocation, including selected and ranged children. */
|
|
6
|
+
export const MAX_ACTION_EXPANSION = 4096;
|
|
4
7
|
const name = z
|
|
5
8
|
.string()
|
|
6
9
|
.regex(/^[a-z][a-zA-Z0-9_]*$/)
|
|
@@ -14,6 +17,13 @@ const path = z
|
|
|
14
17
|
.regex(/^[a-z][a-zA-Z0-9_]*(?:\.[a-z][a-zA-Z0-9_]*)*$/)
|
|
15
18
|
.max(240);
|
|
16
19
|
const instrumentId = name.meta({ "x-udl-reference": "instrument" });
|
|
20
|
+
const objectKindId = name.meta({ "x-udl-reference": "object" });
|
|
21
|
+
|
|
22
|
+
export const udlPartyNameSchema = name;
|
|
23
|
+
|
|
24
|
+
export const udlObjectIdSchema = z.string().min(1).max(160);
|
|
25
|
+
export const udlExternalIdSchema = z.string().min(1).max(2048);
|
|
26
|
+
export const udlObjectRevisionSchema = integer.positive();
|
|
17
27
|
|
|
18
28
|
/** Currency belongs to the document. Accounts and amounts cannot override it. */
|
|
19
29
|
export const udlPartySchema = z.strictObject({
|
|
@@ -21,11 +31,37 @@ export const udlPartySchema = z.strictObject({
|
|
|
21
31
|
role: name.optional(),
|
|
22
32
|
});
|
|
23
33
|
|
|
34
|
+
export const udlFamilySchema = z.strictObject({
|
|
35
|
+
module: name,
|
|
36
|
+
exportPath: path,
|
|
37
|
+
revision: integer.positive(),
|
|
38
|
+
});
|
|
39
|
+
|
|
24
40
|
const fieldBase = {
|
|
25
41
|
name,
|
|
26
42
|
optional: z.literal(true).optional(),
|
|
27
43
|
description: text.optional(),
|
|
44
|
+
sensitive: z.literal(true).optional(),
|
|
28
45
|
};
|
|
46
|
+
|
|
47
|
+
const referenceField = z.strictObject({
|
|
48
|
+
...fieldBase,
|
|
49
|
+
type: z.literal("ref"),
|
|
50
|
+
targetKind: z.enum(["instrument", "object"]),
|
|
51
|
+
targetFamily: udlFamilySchema.optional(),
|
|
52
|
+
target: z.union([name, z.array(name).min(1).max(16)]),
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const listField = z.strictObject({
|
|
56
|
+
...fieldBase,
|
|
57
|
+
type: z.literal("list"),
|
|
58
|
+
item: z.enum(["money", "date", "text", "integer", "ref"]),
|
|
59
|
+
targetKind: z.enum(["instrument", "object"]).optional(),
|
|
60
|
+
targetFamily: udlFamilySchema.optional(),
|
|
61
|
+
target: name.optional(),
|
|
62
|
+
maxItems: integer.min(1).max(366),
|
|
63
|
+
});
|
|
64
|
+
|
|
29
65
|
export const udlFieldSchema = z.discriminatedUnion("type", [
|
|
30
66
|
z.strictObject({
|
|
31
67
|
...fieldBase,
|
|
@@ -41,13 +77,8 @@ export const udlFieldSchema = z.discriminatedUnion("type", [
|
|
|
41
77
|
key: name.optional(),
|
|
42
78
|
book: z.enum(["cash", "claim"]).default("cash"),
|
|
43
79
|
contra: z.literal(true).optional(),
|
|
44
|
-
external: z.literal(true).optional(),
|
|
45
|
-
}),
|
|
46
|
-
z.strictObject({
|
|
47
|
-
...fieldBase,
|
|
48
|
-
type: z.literal("ref"),
|
|
49
|
-
target: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
50
80
|
}),
|
|
81
|
+
referenceField,
|
|
51
82
|
z.strictObject({
|
|
52
83
|
...fieldBase,
|
|
53
84
|
type: z.literal("date"),
|
|
@@ -62,7 +93,13 @@ export const udlFieldSchema = z.discriminatedUnion("type", [
|
|
|
62
93
|
...fieldBase,
|
|
63
94
|
type: z.literal("text"),
|
|
64
95
|
value: text.optional(),
|
|
96
|
+
minLength: integer.positive().max(2048).optional(),
|
|
65
97
|
maxLength: integer.positive().max(2048).optional(),
|
|
98
|
+
// One anchored ASCII character class and a fixed repetition. No executable patterns.
|
|
99
|
+
pattern: z
|
|
100
|
+
.string()
|
|
101
|
+
.regex(/^\^\[[A-Za-z0-9-]+\]\{[1-9][0-9]{0,3}\}\$$/)
|
|
102
|
+
.optional(),
|
|
66
103
|
}),
|
|
67
104
|
z.strictObject({
|
|
68
105
|
...fieldBase,
|
|
@@ -87,14 +124,88 @@ export const udlFieldSchema = z.discriminatedUnion("type", [
|
|
|
87
124
|
values: z.array(name).min(1).max(64),
|
|
88
125
|
value: name.optional(),
|
|
89
126
|
}),
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
127
|
+
listField,
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
const [
|
|
131
|
+
moneyField,
|
|
132
|
+
,
|
|
133
|
+
refField,
|
|
134
|
+
dateField,
|
|
135
|
+
durationField,
|
|
136
|
+
textField,
|
|
137
|
+
integerField,
|
|
138
|
+
percentField,
|
|
139
|
+
booleanField,
|
|
140
|
+
enumField,
|
|
141
|
+
boundedListField,
|
|
142
|
+
] = udlFieldSchema.options;
|
|
143
|
+
|
|
144
|
+
export const udlObjectFieldSchema = z.discriminatedUnion("type", [
|
|
145
|
+
moneyField,
|
|
146
|
+
refField,
|
|
147
|
+
dateField,
|
|
148
|
+
durationField,
|
|
149
|
+
textField,
|
|
150
|
+
integerField,
|
|
151
|
+
percentField,
|
|
152
|
+
booleanField,
|
|
153
|
+
enumField,
|
|
154
|
+
boundedListField,
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
export const udlSubjectRequirementSchema = z.strictObject({
|
|
158
|
+
field: udlObjectFieldSchema,
|
|
159
|
+
// Present only for an authored rename.
|
|
160
|
+
objectField: name.optional(),
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
export const adapterSubjectSnapshotSchema = z.strictObject({
|
|
164
|
+
provider: text,
|
|
165
|
+
capability: text,
|
|
166
|
+
operation: text,
|
|
167
|
+
declarationDigest: z.string().regex(/^[a-f0-9]{64}$/),
|
|
168
|
+
requirements: z.array(udlObjectFieldSchema).max(128),
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
export const udlActionSubjectSchema = z.strictObject({
|
|
172
|
+
requirements: z.array(udlSubjectRequirementSchema).max(128),
|
|
173
|
+
adapters: z
|
|
174
|
+
.array(
|
|
175
|
+
z.strictObject({
|
|
176
|
+
binding: name,
|
|
177
|
+
// null means unavailable, never "no requirements".
|
|
178
|
+
snapshot: adapterSubjectSnapshotSchema.nullable(),
|
|
179
|
+
renames: z.record(name, name).optional(),
|
|
180
|
+
}),
|
|
181
|
+
)
|
|
182
|
+
.max(16),
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
export const subjectPartyRoles = ["owner", "actor", "operator"] as const;
|
|
186
|
+
export const attachmentPartyBindingSchema = z.union([
|
|
187
|
+
z.strictObject({ role: z.enum(subjectPartyRoles) }),
|
|
188
|
+
z.strictObject({ party: name }),
|
|
97
189
|
]);
|
|
190
|
+
export type AttachmentPartyBinding = z.infer<
|
|
191
|
+
typeof attachmentPartyBindingSchema
|
|
192
|
+
>;
|
|
193
|
+
export const udlObjectAttachmentSchema = z.strictObject({
|
|
194
|
+
name,
|
|
195
|
+
instrument: instrumentId,
|
|
196
|
+
parties: z.record(name, attachmentPartyBindingSchema),
|
|
197
|
+
});
|
|
198
|
+
export type SubjectPartyRole = (typeof subjectPartyRoles)[number];
|
|
199
|
+
export type UdlObjectAttachment = z.infer<typeof udlObjectAttachmentSchema>;
|
|
200
|
+
|
|
201
|
+
export const udlObjectKindSchema = z.strictObject({
|
|
202
|
+
id: objectKindId,
|
|
203
|
+
title: text,
|
|
204
|
+
authoredFields: z.array(name).max(256),
|
|
205
|
+
attachments: z.array(udlObjectAttachmentSchema).max(256),
|
|
206
|
+
fields: z.array(udlObjectFieldSchema).max(256),
|
|
207
|
+
columns: z.array(name).max(8),
|
|
208
|
+
});
|
|
98
209
|
|
|
99
210
|
/** Values are constants or resolved typed paths, never executable strings. */
|
|
100
211
|
export const udlValueSchema = z.union([
|
|
@@ -105,6 +216,7 @@ const value = udlValueSchema;
|
|
|
105
216
|
const values = z.array(value).min(1).max(256);
|
|
106
217
|
|
|
107
218
|
const selection = z.strictObject({
|
|
219
|
+
family: udlFamilySchema.optional(),
|
|
108
220
|
instrument: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
109
221
|
reference: name,
|
|
110
222
|
anchor: path,
|
|
@@ -183,6 +295,13 @@ export const udlCalculationSchema = z.discriminatedUnion("op", [
|
|
|
183
295
|
}),
|
|
184
296
|
]);
|
|
185
297
|
|
|
298
|
+
const comparisonRequirement = z.strictObject({
|
|
299
|
+
kind: z.literal("compare"),
|
|
300
|
+
left: value,
|
|
301
|
+
operator: z.enum(["==", "!=", "<", "<=", ">", ">="]),
|
|
302
|
+
right: value,
|
|
303
|
+
});
|
|
304
|
+
|
|
186
305
|
export const udlRequirementSchema = z.discriminatedUnion("kind", [
|
|
187
306
|
z.strictObject({
|
|
188
307
|
kind: z.literal("hours"),
|
|
@@ -191,12 +310,7 @@ export const udlRequirementSchema = z.discriminatedUnion("kind", [
|
|
|
191
310
|
end: integer.min(0).max(23),
|
|
192
311
|
timezone: text,
|
|
193
312
|
}),
|
|
194
|
-
|
|
195
|
-
kind: z.literal("compare"),
|
|
196
|
-
left: value,
|
|
197
|
-
operator: z.enum(["==", "!=", "<", "<=", ">", ">="]),
|
|
198
|
-
right: value,
|
|
199
|
-
}),
|
|
313
|
+
comparisonRequirement,
|
|
200
314
|
z.strictObject({
|
|
201
315
|
kind: z.literal("state"),
|
|
202
316
|
reference: path,
|
|
@@ -220,9 +334,12 @@ export const udlRequirementSchema = z.discriminatedUnion("kind", [
|
|
|
220
334
|
party: name,
|
|
221
335
|
action: name.optional(),
|
|
222
336
|
decision: z.enum(["approved", "declined"]),
|
|
337
|
+
differentFromInitiator: z.literal(true).optional(),
|
|
338
|
+
protectedRequest: path.default("self"),
|
|
223
339
|
}),
|
|
224
340
|
z.strictObject({
|
|
225
341
|
kind: z.literal("evidence"),
|
|
342
|
+
instruction: path.optional(),
|
|
226
343
|
subject: path,
|
|
227
344
|
family: name,
|
|
228
345
|
check: name,
|
|
@@ -249,6 +366,7 @@ export const udlMoveSchema = z.discriminatedUnion("operation", [
|
|
|
249
366
|
z.strictObject({
|
|
250
367
|
key: name,
|
|
251
368
|
operation: z.literal("internal_transfer.reserve"),
|
|
369
|
+
boundary: z.strictObject({ adapter: name }).optional(),
|
|
252
370
|
amount: value,
|
|
253
371
|
from: path,
|
|
254
372
|
to: path,
|
|
@@ -267,17 +385,48 @@ export const udlMoveSchema = z.discriminatedUnion("operation", [
|
|
|
267
385
|
transfer: path,
|
|
268
386
|
}),
|
|
269
387
|
]);
|
|
270
|
-
const clock = z.strictObject({
|
|
388
|
+
const clock = z.strictObject({
|
|
389
|
+
at: path,
|
|
390
|
+
offset: integer.optional(),
|
|
391
|
+
localDay: z
|
|
392
|
+
.strictObject({
|
|
393
|
+
days: integer.min(0).max(366),
|
|
394
|
+
direction: z.enum(["before", "after"]),
|
|
395
|
+
hour: integer.min(0).max(23),
|
|
396
|
+
timezone: text,
|
|
397
|
+
})
|
|
398
|
+
.optional(),
|
|
399
|
+
});
|
|
271
400
|
export const udlActionSchema = z.strictObject({
|
|
272
401
|
summary: text,
|
|
273
402
|
publicAction: name.optional(),
|
|
403
|
+
expansionLimit: z.literal(8192).optional(),
|
|
404
|
+
humanApproval: z.literal("distinct_member").optional(),
|
|
405
|
+
reminder: z
|
|
406
|
+
.strictObject({
|
|
407
|
+
installment: path,
|
|
408
|
+
recipient: path,
|
|
409
|
+
dueAt: path,
|
|
410
|
+
channel: z.literal("email"),
|
|
411
|
+
template: z.literal("payment_reminder"),
|
|
412
|
+
beforeDays: integer.min(0).max(366),
|
|
413
|
+
overdueDays: integer.min(1).max(366),
|
|
414
|
+
maxPerDay: integer.min(1).max(10),
|
|
415
|
+
startHour: integer.min(0).max(23),
|
|
416
|
+
endHour: integer.min(1).max(24),
|
|
417
|
+
timezone: text,
|
|
418
|
+
})
|
|
419
|
+
.optional(),
|
|
274
420
|
event: text,
|
|
275
421
|
actor: z.union([
|
|
276
422
|
z.literal("caller"),
|
|
277
423
|
z.literal("clock"),
|
|
278
424
|
z.strictObject({ party: name }),
|
|
279
|
-
z.strictObject({
|
|
425
|
+
z.strictObject({
|
|
426
|
+
parent: z.union([instrumentId, z.array(instrumentId).min(1).max(16)]),
|
|
427
|
+
}),
|
|
280
428
|
]),
|
|
429
|
+
subject: udlActionSubjectSchema.optional(),
|
|
281
430
|
input: z.array(udlFieldSchema).max(128),
|
|
282
431
|
requires: z.array(udlRequirementSchema).max(128),
|
|
283
432
|
due: clock.optional(),
|
|
@@ -292,16 +441,26 @@ export const udlActionSchema = z.strictObject({
|
|
|
292
441
|
instrument: instrumentId,
|
|
293
442
|
action: z.literal("create"),
|
|
294
443
|
input: z.record(name, value),
|
|
444
|
+
guard: comparisonRequirement.optional(),
|
|
445
|
+
range: z
|
|
446
|
+
.strictObject({
|
|
447
|
+
count: value,
|
|
448
|
+
maximum: integer.min(1).max(366),
|
|
449
|
+
bind: name,
|
|
450
|
+
})
|
|
451
|
+
.optional(),
|
|
295
452
|
}),
|
|
296
453
|
z.strictObject({
|
|
297
454
|
reference: path,
|
|
298
455
|
action: name,
|
|
299
456
|
input: z.record(name, value),
|
|
457
|
+
guard: comparisonRequirement.optional(),
|
|
300
458
|
}),
|
|
301
459
|
z.strictObject({
|
|
302
460
|
selection,
|
|
303
461
|
action: name,
|
|
304
462
|
input: z.record(name, value),
|
|
463
|
+
guard: comparisonRequirement.optional(),
|
|
305
464
|
}),
|
|
306
465
|
]),
|
|
307
466
|
)
|
|
@@ -309,6 +468,7 @@ export const udlActionSchema = z.strictObject({
|
|
|
309
468
|
.optional(),
|
|
310
469
|
approval: z
|
|
311
470
|
.strictObject({
|
|
471
|
+
protectedRequest: path.default("self"),
|
|
312
472
|
target: path,
|
|
313
473
|
action: name,
|
|
314
474
|
party: name,
|
|
@@ -327,7 +487,11 @@ export const udlLifecycleSchema = z.strictObject({
|
|
|
327
487
|
),
|
|
328
488
|
});
|
|
329
489
|
export const udlInstrumentSchema = z.strictObject({
|
|
490
|
+
reports: z.array(reportDefinitionSchema).max(16).optional(),
|
|
491
|
+
revisioned: z.literal(true).optional(),
|
|
492
|
+
family: udlFamilySchema.optional(),
|
|
330
493
|
id: instrumentId,
|
|
494
|
+
subject: objectKindId.optional(),
|
|
331
495
|
title: text,
|
|
332
496
|
summary: text,
|
|
333
497
|
fields: z.array(udlFieldSchema).max(256),
|
|
@@ -348,9 +512,11 @@ export const udlDocumentSchema = z.strictObject({
|
|
|
348
512
|
title: text,
|
|
349
513
|
currency: z.literal("SAR"),
|
|
350
514
|
parties: z.record(name, udlPartySchema),
|
|
351
|
-
|
|
515
|
+
objects: z.array(udlObjectKindSchema).max(256),
|
|
516
|
+
instruments: z.array(udlInstrumentSchema).max(256),
|
|
352
517
|
});
|
|
353
518
|
|
|
519
|
+
export type UdlFamily = z.infer<typeof udlFamilySchema>;
|
|
354
520
|
export type UdlDocument = z.infer<typeof udlDocumentSchema>;
|
|
355
521
|
export type UdlInstrument = z.infer<typeof udlInstrumentSchema>;
|
|
356
522
|
export type UdlField = z.infer<typeof udlFieldSchema>;
|
|
@@ -364,3 +530,33 @@ export type UdlLifecycle = z.infer<typeof udlLifecycleSchema>;
|
|
|
364
530
|
export type UdlKernelOperation = z.infer<typeof udlKernelOperationSchema>;
|
|
365
531
|
|
|
366
532
|
export type UdlSelection = z.infer<typeof selection>;
|
|
533
|
+
|
|
534
|
+
export type UdlObjectField = z.infer<typeof udlObjectFieldSchema>;
|
|
535
|
+
export type UdlObjectKind = z.infer<typeof udlObjectKindSchema>;
|
|
536
|
+
export type UdlActionSubject = z.infer<typeof udlActionSubjectSchema>;
|
|
537
|
+
export type UdlSubjectRequirement = z.infer<typeof udlSubjectRequirementSchema>;
|
|
538
|
+
export type UdlAdapterSubjectSnapshot = z.infer<
|
|
539
|
+
typeof adapterSubjectSnapshotSchema
|
|
540
|
+
>;
|
|
541
|
+
|
|
542
|
+
/** Names and display text may differ; executable constraints must match. */
|
|
543
|
+
export function sameObjectField(
|
|
544
|
+
left: UdlObjectField,
|
|
545
|
+
right: UdlObjectField,
|
|
546
|
+
): boolean {
|
|
547
|
+
const signature = (field: UdlObjectField) =>
|
|
548
|
+
JSON.stringify(
|
|
549
|
+
Object.fromEntries(
|
|
550
|
+
Object.entries(field)
|
|
551
|
+
.filter(
|
|
552
|
+
([key, value]) =>
|
|
553
|
+
!["name", "description", "optional"].includes(key) &&
|
|
554
|
+
value !== undefined,
|
|
555
|
+
)
|
|
556
|
+
.sort(([left], [right]) =>
|
|
557
|
+
left < right ? -1 : left > right ? 1 : 0,
|
|
558
|
+
),
|
|
559
|
+
),
|
|
560
|
+
);
|
|
561
|
+
return signature(left) === signature(right);
|
|
562
|
+
}
|