kintone-migrator 0.24.1 → 0.24.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/dist/index.mjs +738 -766
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -25,7 +25,8 @@ const ActionErrorCode = {
|
|
|
25
25
|
AcInvalidConfigStructure: "AC_INVALID_CONFIG_STRUCTURE",
|
|
26
26
|
AcInvalidSrcType: "AC_INVALID_SRC_TYPE",
|
|
27
27
|
AcInvalidEntityType: "AC_INVALID_ENTITY_TYPE",
|
|
28
|
-
AcEmptyActionName: "AC_EMPTY_ACTION_NAME"
|
|
28
|
+
AcEmptyActionName: "AC_EMPTY_ACTION_NAME",
|
|
29
|
+
AcDuplicateIndex: "AC_DUPLICATE_INDEX"
|
|
29
30
|
};
|
|
30
31
|
|
|
31
32
|
//#endregion
|
|
@@ -67,6 +68,7 @@ const FieldPermissionErrorCode = {
|
|
|
67
68
|
FpInvalidConfigStructure: "FP_INVALID_CONFIG_STRUCTURE",
|
|
68
69
|
FpInvalidAccessibility: "FP_INVALID_ACCESSIBILITY",
|
|
69
70
|
FpInvalidEntityType: "FP_INVALID_ENTITY_TYPE",
|
|
71
|
+
FpInvalidBooleanField: "FP_INVALID_BOOLEAN_FIELD",
|
|
70
72
|
FpEmptyFieldCode: "FP_EMPTY_FIELD_CODE",
|
|
71
73
|
FpEmptyEntityCode: "FP_EMPTY_ENTITY_CODE",
|
|
72
74
|
FpDuplicateFieldCode: "FP_DUPLICATE_FIELD_CODE"
|
|
@@ -94,7 +96,9 @@ const GeneralSettingsErrorCode = {
|
|
|
94
96
|
GsInvalidConfigYaml: "GS_INVALID_CONFIG_YAML",
|
|
95
97
|
GsInvalidConfigStructure: "GS_INVALID_CONFIG_STRUCTURE",
|
|
96
98
|
GsInvalidTheme: "GS_INVALID_THEME",
|
|
97
|
-
GsInvalidIconType: "GS_INVALID_ICON_TYPE"
|
|
99
|
+
GsInvalidIconType: "GS_INVALID_ICON_TYPE",
|
|
100
|
+
GsInvalidBooleanField: "GS_INVALID_BOOLEAN_FIELD",
|
|
101
|
+
GsInvalidNumberPrecision: "GS_INVALID_NUMBER_PRECISION"
|
|
98
102
|
};
|
|
99
103
|
|
|
100
104
|
//#endregion
|
|
@@ -106,7 +110,9 @@ const NotificationErrorCode = {
|
|
|
106
110
|
NtInvalidEntityType: "NT_INVALID_ENTITY_TYPE",
|
|
107
111
|
NtEmptyEntityCode: "NT_EMPTY_ENTITY_CODE",
|
|
108
112
|
NtMissingRequiredField: "NT_MISSING_REQUIRED_FIELD",
|
|
109
|
-
NtConflictingTimingFields: "NT_CONFLICTING_TIMING_FIELDS"
|
|
113
|
+
NtConflictingTimingFields: "NT_CONFLICTING_TIMING_FIELDS",
|
|
114
|
+
NtInvalidHoursLater: "NT_INVALID_HOURS_LATER",
|
|
115
|
+
NtInvalidDaysLater: "NT_INVALID_DAYS_LATER"
|
|
110
116
|
};
|
|
111
117
|
|
|
112
118
|
//#endregion
|
|
@@ -115,7 +121,8 @@ const PluginErrorCode = {
|
|
|
115
121
|
PlEmptyConfigText: "PL_EMPTY_CONFIG_TEXT",
|
|
116
122
|
PlInvalidConfigYaml: "PL_INVALID_CONFIG_YAML",
|
|
117
123
|
PlInvalidConfigStructure: "PL_INVALID_CONFIG_STRUCTURE",
|
|
118
|
-
PlEmptyPluginId: "PL_EMPTY_PLUGIN_ID"
|
|
124
|
+
PlEmptyPluginId: "PL_EMPTY_PLUGIN_ID",
|
|
125
|
+
PlDuplicatePluginId: "PL_DUPLICATE_PLUGIN_ID"
|
|
119
126
|
};
|
|
120
127
|
|
|
121
128
|
//#endregion
|
|
@@ -126,7 +133,9 @@ const ProcessManagementErrorCode = {
|
|
|
126
133
|
PmInvalidConfigStructure: "PM_INVALID_CONFIG_STRUCTURE",
|
|
127
134
|
PmInvalidAssigneeType: "PM_INVALID_ASSIGNEE_TYPE",
|
|
128
135
|
PmInvalidEntityType: "PM_INVALID_ENTITY_TYPE",
|
|
129
|
-
|
|
136
|
+
PmInvalidBooleanField: "PM_INVALID_BOOLEAN_FIELD",
|
|
137
|
+
PmInvalidActionReference: "PM_INVALID_ACTION_REFERENCE",
|
|
138
|
+
PmDuplicateActionName: "PM_DUPLICATE_ACTION_NAME"
|
|
130
139
|
};
|
|
131
140
|
|
|
132
141
|
//#endregion
|
|
@@ -150,7 +159,8 @@ const RecordPermissionErrorCode = {
|
|
|
150
159
|
RpInvalidConfigStructure: "RP_INVALID_CONFIG_STRUCTURE",
|
|
151
160
|
RpInvalidEntityType: "RP_INVALID_ENTITY_TYPE",
|
|
152
161
|
RpEmptyEntityCode: "RP_EMPTY_ENTITY_CODE",
|
|
153
|
-
RpInvalidPermissionValue: "RP_INVALID_PERMISSION_VALUE"
|
|
162
|
+
RpInvalidPermissionValue: "RP_INVALID_PERMISSION_VALUE",
|
|
163
|
+
RpDuplicateEntity: "RP_DUPLICATE_ENTITY"
|
|
154
164
|
};
|
|
155
165
|
|
|
156
166
|
//#endregion
|
|
@@ -176,6 +186,10 @@ const SeedDataErrorCode = {
|
|
|
176
186
|
SdInvalidKeyFieldValue: "SD_INVALID_KEY_FIELD_VALUE"
|
|
177
187
|
};
|
|
178
188
|
|
|
189
|
+
//#endregion
|
|
190
|
+
//#region src/core/domain/services/errorCode.ts
|
|
191
|
+
const DomainServiceErrorCode = { YamlSerializationFailed: "DS_YAML_SERIALIZATION_FAILED" };
|
|
192
|
+
|
|
179
193
|
//#endregion
|
|
180
194
|
//#region src/core/domain/view/errorCode.ts
|
|
181
195
|
const ViewErrorCode = {
|
|
@@ -184,7 +198,8 @@ const ViewErrorCode = {
|
|
|
184
198
|
VwInvalidConfigStructure: "VW_INVALID_CONFIG_STRUCTURE",
|
|
185
199
|
VwInvalidViewType: "VW_INVALID_VIEW_TYPE",
|
|
186
200
|
VwInvalidDeviceType: "VW_INVALID_DEVICE_TYPE",
|
|
187
|
-
VwEmptyViewName: "VW_EMPTY_VIEW_NAME"
|
|
201
|
+
VwEmptyViewName: "VW_EMPTY_VIEW_NAME",
|
|
202
|
+
VwInvalidIndex: "VW_INVALID_INDEX"
|
|
188
203
|
};
|
|
189
204
|
|
|
190
205
|
//#endregion
|
|
@@ -204,6 +219,7 @@ const BusinessRuleErrorCode = {
|
|
|
204
219
|
...RecordPermissionErrorCode,
|
|
205
220
|
...ReportErrorCode,
|
|
206
221
|
...SeedDataErrorCode,
|
|
222
|
+
...DomainServiceErrorCode,
|
|
207
223
|
...ViewErrorCode
|
|
208
224
|
};
|
|
209
225
|
/**
|
|
@@ -339,10 +355,6 @@ function isRecord(value) {
|
|
|
339
355
|
//#endregion
|
|
340
356
|
//#region src/core/domain/typeGuards.ts
|
|
341
357
|
/**
|
|
342
|
-
* Type guard utilities for safe runtime type narrowing.
|
|
343
|
-
* Use these functions instead of `as` casts when working with `unknown` values.
|
|
344
|
-
*/
|
|
345
|
-
/**
|
|
346
358
|
* Narrows `unknown` to `{ code: string }`.
|
|
347
359
|
*/
|
|
348
360
|
function hasCode(value) {
|
|
@@ -364,61 +376,121 @@ function hasOptionalType(value) {
|
|
|
364
376
|
if (!isRecord(value)) return false;
|
|
365
377
|
return value.type === void 0 || typeof value.type === "string";
|
|
366
378
|
}
|
|
379
|
+
/**
|
|
380
|
+
* Strict boolean validation — rejects non-boolean values.
|
|
381
|
+
* Returns the boolean value if valid, or `defaultValue` when the value is undefined/null.
|
|
382
|
+
* Throws `BusinessRuleError` when the value is present but not a boolean.
|
|
383
|
+
*/
|
|
384
|
+
function parseStrictBoolean(value, fieldName, context, errorCode, defaultValue) {
|
|
385
|
+
if (value === void 0 || value === null) {
|
|
386
|
+
if (defaultValue !== void 0) return defaultValue;
|
|
387
|
+
throw new BusinessRuleError(errorCode, `${context} must have a boolean "${fieldName}" property`);
|
|
388
|
+
}
|
|
389
|
+
if (typeof value !== "boolean") throw new BusinessRuleError(errorCode, `${context} has invalid "${fieldName}" value: ${String(value)}. Must be a boolean`);
|
|
390
|
+
return value;
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Validates that an unknown value is a string within an allowed set and returns a typed value.
|
|
394
|
+
* Replaces manual `typeof` + `Set.has` + `as` cast patterns.
|
|
395
|
+
*/
|
|
396
|
+
function parseEnum(value, validValues, errorCode, message) {
|
|
397
|
+
if (typeof value !== "string" || !validValues.has(value)) throw new BusinessRuleError(errorCode, message);
|
|
398
|
+
return value;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Shared entity parsing logic for domains that use `{ type, code }` entities.
|
|
402
|
+
* Handles common validation: isRecord check, type enum validation, and code non-empty check.
|
|
403
|
+
* Use `allowEmptyCode` to permit empty/missing code for specific entity types (e.g., CREATOR).
|
|
404
|
+
*/
|
|
405
|
+
function parseEntityBase(raw, index, validTypes, errorCodes, options) {
|
|
406
|
+
if (!isRecord(raw)) throw new BusinessRuleError(errorCodes.invalidStructure, `Entity at index ${index} must be an object`);
|
|
407
|
+
const type = parseEnum(raw.type, validTypes, errorCodes.invalidType, `Entity at index ${index} has invalid type: ${String(raw.type)}. Must be ${[...validTypes].join(", ")}`);
|
|
408
|
+
if (options?.allowEmptyCode?.(type)) return {
|
|
409
|
+
type,
|
|
410
|
+
code: typeof raw.code === "string" ? raw.code : ""
|
|
411
|
+
};
|
|
412
|
+
if (typeof raw.code !== "string" || raw.code.length === 0) throw new BusinessRuleError(errorCodes.emptyCode, `Entity at index ${index} must have a non-empty "code" property`);
|
|
413
|
+
return {
|
|
414
|
+
type,
|
|
415
|
+
code: raw.code
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
//#endregion
|
|
420
|
+
//#region src/core/domain/services/yamlConfigParser.ts
|
|
421
|
+
function parseYamlConfig(rawText, errorCodes, domainLabel) {
|
|
422
|
+
if (rawText.trim().length === 0) throw new BusinessRuleError(errorCodes.emptyConfigText, `${domainLabel} config text is empty`);
|
|
423
|
+
let parsed;
|
|
424
|
+
try {
|
|
425
|
+
parsed = parse(rawText);
|
|
426
|
+
} catch (error) {
|
|
427
|
+
throw new BusinessRuleError(errorCodes.invalidConfigYaml, `Failed to parse ${domainLabel} YAML: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
428
|
+
}
|
|
429
|
+
if (!isRecord(parsed)) throw new BusinessRuleError(errorCodes.invalidConfigStructure, `${domainLabel} config must be a YAML object`);
|
|
430
|
+
return parsed;
|
|
431
|
+
}
|
|
367
432
|
|
|
368
433
|
//#endregion
|
|
369
434
|
//#region src/core/domain/action/valueObject.ts
|
|
370
|
-
const
|
|
371
|
-
const
|
|
435
|
+
const SRC_TYPES = ["FIELD", "RECORD_URL"];
|
|
436
|
+
const VALID_SRC_TYPES = new Set(SRC_TYPES);
|
|
437
|
+
function isActionMappingSrcType(value) {
|
|
438
|
+
return VALID_SRC_TYPES.has(value);
|
|
439
|
+
}
|
|
440
|
+
const ENTITY_TYPES$1 = [
|
|
372
441
|
"USER",
|
|
373
442
|
"GROUP",
|
|
374
443
|
"ORGANIZATION"
|
|
375
|
-
]
|
|
444
|
+
];
|
|
445
|
+
const VALID_ENTITY_TYPES$9 = new Set(ENTITY_TYPES$1);
|
|
446
|
+
function isActionEntityType(value) {
|
|
447
|
+
return VALID_ENTITY_TYPES$9.has(value);
|
|
448
|
+
}
|
|
376
449
|
|
|
377
450
|
//#endregion
|
|
378
451
|
//#region src/core/domain/action/services/configParser.ts
|
|
379
452
|
function parseDestApp(raw, actionName) {
|
|
380
453
|
if (!isRecord(raw)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" destApp must be an object`);
|
|
381
|
-
const obj = raw;
|
|
382
454
|
const result = {};
|
|
383
|
-
if (
|
|
384
|
-
if (
|
|
455
|
+
if (raw.app !== void 0 && raw.app !== null) result.app = String(raw.app);
|
|
456
|
+
if (raw.code !== void 0 && raw.code !== null) result.code = String(raw.code);
|
|
457
|
+
if (result.app === void 0 && result.code === void 0) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" destApp must have at least "app" or "code" property`);
|
|
385
458
|
return result;
|
|
386
459
|
}
|
|
387
460
|
function parseMapping(raw, index, actionName) {
|
|
388
461
|
if (!isRecord(raw)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" mapping at index ${index} must be an object`);
|
|
389
|
-
|
|
390
|
-
if (typeof
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
...obj.srcField !== void 0 && obj.srcField !== null && typeof obj.srcField === "string" ? { srcField: obj.srcField } : {}
|
|
462
|
+
if (typeof raw.srcType !== "string" || !isActionMappingSrcType(raw.srcType)) throw new BusinessRuleError(ActionErrorCode.AcInvalidSrcType, `Action "${actionName}" mapping at index ${index} has invalid srcType: ${String(raw.srcType)}. Must be FIELD or RECORD_URL`);
|
|
463
|
+
if (typeof raw.destField !== "string" || raw.destField.length === 0) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" mapping at index ${index} must have a non-empty "destField" property`);
|
|
464
|
+
const result = {
|
|
465
|
+
srcType: raw.srcType,
|
|
466
|
+
destField: raw.destField,
|
|
467
|
+
...raw.srcField !== void 0 && raw.srcField !== null && typeof raw.srcField === "string" ? { srcField: raw.srcField } : {}
|
|
396
468
|
};
|
|
469
|
+
if (result.srcType === "FIELD" && result.srcField === void 0) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" mapping at index ${index} with srcType "FIELD" must have a "srcField" property`);
|
|
470
|
+
return result;
|
|
397
471
|
}
|
|
398
472
|
function parseEntity$4(raw, index, actionName) {
|
|
399
473
|
if (!isRecord(raw)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" entity at index ${index} must be an object`);
|
|
400
|
-
|
|
401
|
-
if (typeof
|
|
402
|
-
if (typeof obj.code !== "string" || obj.code.length === 0) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" entity at index ${index} must have a non-empty "code" property`);
|
|
474
|
+
if (typeof raw.type !== "string" || !isActionEntityType(raw.type)) throw new BusinessRuleError(ActionErrorCode.AcInvalidEntityType, `Action "${actionName}" entity at index ${index} has invalid type: ${String(raw.type)}. Must be USER, GROUP, or ORGANIZATION`);
|
|
475
|
+
if (typeof raw.code !== "string" || raw.code.length === 0) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" entity at index ${index} must have a non-empty "code" property`);
|
|
403
476
|
return {
|
|
404
|
-
type:
|
|
405
|
-
code:
|
|
477
|
+
type: raw.type,
|
|
478
|
+
code: raw.code
|
|
406
479
|
};
|
|
407
480
|
}
|
|
408
481
|
function parseActionConfig(raw, actionName) {
|
|
409
|
-
if (!isRecord(raw)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" must be an object`);
|
|
410
|
-
const obj = raw;
|
|
411
482
|
if (actionName.length === 0) throw new BusinessRuleError(ActionErrorCode.AcEmptyActionName, "Action name (key) must not be empty");
|
|
412
|
-
if (
|
|
413
|
-
if (!
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
const
|
|
420
|
-
|
|
421
|
-
|
|
483
|
+
if (!isRecord(raw)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" must be an object`);
|
|
484
|
+
if (typeof raw.index !== "number" || !Number.isInteger(raw.index) || raw.index < 0) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" must have a non-negative integer "index" property`);
|
|
485
|
+
if (!isRecord(raw.destApp)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" must have a "destApp" object`);
|
|
486
|
+
const destApp = parseDestApp(raw.destApp, actionName);
|
|
487
|
+
if (!Array.isArray(raw.mappings)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" must have a "mappings" array`);
|
|
488
|
+
const mappings = raw.mappings.map((item, i) => parseMapping(item, i, actionName));
|
|
489
|
+
if (!Array.isArray(raw.entities)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, `Action "${actionName}" must have an "entities" array`);
|
|
490
|
+
const entities = raw.entities.map((item, i) => parseEntity$4(item, i, actionName));
|
|
491
|
+
const filterCond = typeof raw.filterCond === "string" ? raw.filterCond : "";
|
|
492
|
+
return {
|
|
493
|
+
index: raw.index,
|
|
422
494
|
name: actionName,
|
|
423
495
|
destApp,
|
|
424
496
|
mappings,
|
|
@@ -427,19 +499,20 @@ function parseActionConfig(raw, actionName) {
|
|
|
427
499
|
};
|
|
428
500
|
}
|
|
429
501
|
const ActionConfigParser = { parse: (rawText) => {
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
}
|
|
435
|
-
throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
436
|
-
}
|
|
437
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, "Config must be a YAML object");
|
|
438
|
-
const obj = parsed;
|
|
502
|
+
const obj = parseYamlConfig(rawText, {
|
|
503
|
+
emptyConfigText: ActionErrorCode.AcEmptyConfigText,
|
|
504
|
+
invalidConfigYaml: ActionErrorCode.AcInvalidConfigYaml,
|
|
505
|
+
invalidConfigStructure: ActionErrorCode.AcInvalidConfigStructure
|
|
506
|
+
}, "Action");
|
|
439
507
|
if (!isRecord(obj.actions)) throw new BusinessRuleError(ActionErrorCode.AcInvalidConfigStructure, "Config must have an \"actions\" object");
|
|
440
508
|
const rawActions = obj.actions;
|
|
441
509
|
const actions = {};
|
|
442
510
|
for (const [key, value] of Object.entries(rawActions)) actions[key] = parseActionConfig(value, key);
|
|
511
|
+
const seenIndices = /* @__PURE__ */ new Set();
|
|
512
|
+
for (const [key, action] of Object.entries(actions)) {
|
|
513
|
+
if (seenIndices.has(action.index)) throw new BusinessRuleError(ActionErrorCode.AcDuplicateIndex, `Duplicate action index ${action.index} found in action "${key}"`);
|
|
514
|
+
seenIndices.add(action.index);
|
|
515
|
+
}
|
|
443
516
|
return { actions };
|
|
444
517
|
} };
|
|
445
518
|
|
|
@@ -471,7 +544,7 @@ function fromKintoneDestApp(raw) {
|
|
|
471
544
|
return result;
|
|
472
545
|
}
|
|
473
546
|
function fromKintoneMapping(raw) {
|
|
474
|
-
if (!
|
|
547
|
+
if (!isActionMappingSrcType(raw.srcType)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected srcType value from kintone API: ${raw.srcType}`);
|
|
475
548
|
return {
|
|
476
549
|
srcType: raw.srcType,
|
|
477
550
|
destField: raw.destField,
|
|
@@ -479,15 +552,17 @@ function fromKintoneMapping(raw) {
|
|
|
479
552
|
};
|
|
480
553
|
}
|
|
481
554
|
function fromKintoneEntity$4(raw) {
|
|
482
|
-
if (!
|
|
555
|
+
if (!isActionEntityType(raw.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected entity type from kintone API: ${raw.type}`);
|
|
483
556
|
return {
|
|
484
557
|
type: raw.type,
|
|
485
558
|
code: raw.code
|
|
486
559
|
};
|
|
487
560
|
}
|
|
488
561
|
function fromKintoneAction$1(raw) {
|
|
562
|
+
const index = Number(raw.index);
|
|
563
|
+
if (!Number.isFinite(index)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected non-numeric index from kintone API: ${raw.index}`);
|
|
489
564
|
return {
|
|
490
|
-
index
|
|
565
|
+
index,
|
|
491
566
|
name: raw.name,
|
|
492
567
|
destApp: fromKintoneDestApp(raw.destApp),
|
|
493
568
|
mappings: raw.mappings.map(fromKintoneMapping),
|
|
@@ -665,25 +740,42 @@ function createLocalFileActionStorage(filePath) {
|
|
|
665
740
|
}
|
|
666
741
|
|
|
667
742
|
//#endregion
|
|
668
|
-
//#region src/core/
|
|
669
|
-
const
|
|
743
|
+
//#region src/core/domain/customization/valueObject.ts
|
|
744
|
+
const SCOPES = [
|
|
670
745
|
"ALL",
|
|
671
746
|
"ADMIN",
|
|
672
747
|
"NONE"
|
|
673
|
-
]
|
|
748
|
+
];
|
|
749
|
+
const VALID_SCOPES = new Set(SCOPES);
|
|
750
|
+
function isCustomizationScope(value) {
|
|
751
|
+
return VALID_SCOPES.has(value);
|
|
752
|
+
}
|
|
753
|
+
const RESOURCE_TYPES = ["FILE", "URL"];
|
|
754
|
+
const VALID_RESOURCE_TYPES = new Set(RESOURCE_TYPES);
|
|
755
|
+
function isResourceType(value) {
|
|
756
|
+
return VALID_RESOURCE_TYPES.has(value);
|
|
757
|
+
}
|
|
758
|
+
const DEFAULT_CUSTOMIZATION_SCOPE = "ALL";
|
|
759
|
+
|
|
760
|
+
//#endregion
|
|
761
|
+
//#region src/core/adapters/kintone/customizationConfigurator.ts
|
|
674
762
|
function fromKintoneResource(raw) {
|
|
675
|
-
if (raw.type === "FILE"
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
763
|
+
if (raw.type === "FILE") {
|
|
764
|
+
if (!raw.file) throw new SystemError(SystemErrorCode.ExternalApiError, "FILE resource from kintone API is missing file metadata");
|
|
765
|
+
return {
|
|
766
|
+
type: "FILE",
|
|
767
|
+
file: {
|
|
768
|
+
fileKey: raw.file.fileKey,
|
|
769
|
+
name: raw.file.name,
|
|
770
|
+
contentType: raw.file.contentType,
|
|
771
|
+
size: raw.file.size
|
|
772
|
+
}
|
|
773
|
+
};
|
|
774
|
+
}
|
|
775
|
+
if (!raw.url) throw new SystemError(SystemErrorCode.ExternalApiError, "URL resource from kintone API is missing url property");
|
|
684
776
|
return {
|
|
685
777
|
type: "URL",
|
|
686
|
-
url: raw.url
|
|
778
|
+
url: raw.url
|
|
687
779
|
};
|
|
688
780
|
}
|
|
689
781
|
function fromKintoneResourceList(raw) {
|
|
@@ -714,7 +806,7 @@ var KintoneCustomizationConfigurator = class {
|
|
|
714
806
|
preview: true
|
|
715
807
|
});
|
|
716
808
|
const rawScope = String(response.scope);
|
|
717
|
-
if (!
|
|
809
|
+
if (!isCustomizationScope(rawScope)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected scope value from kintone API: ${rawScope}`);
|
|
718
810
|
return {
|
|
719
811
|
scope: rawScope,
|
|
720
812
|
desktop: {
|
|
@@ -1799,7 +1891,7 @@ function parseAuth(raw) {
|
|
|
1799
1891
|
}
|
|
1800
1892
|
throw new BusinessRuleError(ProjectConfigErrorCode.PcInvalidAuthConfig, "Auth must have either apiToken or username/password");
|
|
1801
1893
|
}
|
|
1802
|
-
const ConfigParser
|
|
1894
|
+
const ConfigParser = { parse: parseProjectConfig };
|
|
1803
1895
|
|
|
1804
1896
|
//#endregion
|
|
1805
1897
|
//#region src/core/application/projectConfig/loadProjectConfig.ts
|
|
@@ -1815,7 +1907,7 @@ function loadProjectConfig(input) {
|
|
|
1815
1907
|
} catch (cause) {
|
|
1816
1908
|
throw new ValidationError(ValidationErrorCode.InvalidInput, "Invalid YAML syntax in config file", cause);
|
|
1817
1909
|
}
|
|
1818
|
-
return ConfigParser
|
|
1910
|
+
return ConfigParser.parse(raw);
|
|
1819
1911
|
}
|
|
1820
1912
|
|
|
1821
1913
|
//#endregion
|
|
@@ -2397,6 +2489,20 @@ var apply_default$12 = define({
|
|
|
2397
2489
|
}
|
|
2398
2490
|
});
|
|
2399
2491
|
|
|
2492
|
+
//#endregion
|
|
2493
|
+
//#region src/core/domain/services/yamlConfigSerializer.ts
|
|
2494
|
+
function serializeToYaml(data) {
|
|
2495
|
+
try {
|
|
2496
|
+
return stringify(data, {
|
|
2497
|
+
lineWidth: 0,
|
|
2498
|
+
defaultKeyType: "PLAIN",
|
|
2499
|
+
defaultStringType: "PLAIN"
|
|
2500
|
+
});
|
|
2501
|
+
} catch (error) {
|
|
2502
|
+
throw new BusinessRuleError(DomainServiceErrorCode.YamlSerializationFailed, `Failed to serialize config to YAML: ${error instanceof Error ? error.message : String(error)}`, error);
|
|
2503
|
+
}
|
|
2504
|
+
}
|
|
2505
|
+
|
|
2400
2506
|
//#endregion
|
|
2401
2507
|
//#region src/core/domain/action/services/configSerializer.ts
|
|
2402
2508
|
function serializeDestApp(destApp) {
|
|
@@ -2433,11 +2539,7 @@ const ActionConfigSerializer = { serialize: (config) => {
|
|
|
2433
2539
|
const actions = {};
|
|
2434
2540
|
for (const [key, value] of Object.entries(config.actions)) actions[key] = serializeActionConfig(value);
|
|
2435
2541
|
serialized.actions = actions;
|
|
2436
|
-
return
|
|
2437
|
-
lineWidth: 0,
|
|
2438
|
-
defaultKeyType: "PLAIN",
|
|
2439
|
-
defaultStringType: "PLAIN"
|
|
2440
|
-
});
|
|
2542
|
+
return serializeToYaml(serialized);
|
|
2441
2543
|
} };
|
|
2442
2544
|
|
|
2443
2545
|
//#endregion
|
|
@@ -2611,12 +2713,24 @@ function buildDiffResult(entries, warnings = []) {
|
|
|
2611
2713
|
};
|
|
2612
2714
|
}
|
|
2613
2715
|
|
|
2716
|
+
//#endregion
|
|
2717
|
+
//#region src/core/domain/services/recordDiffDetector.ts
|
|
2718
|
+
function detectRecordDiff(localRecord, remoteRecord, callbacks) {
|
|
2719
|
+
const entries = [];
|
|
2720
|
+
for (const [key, localValue] of Object.entries(localRecord)) if (!Object.hasOwn(remoteRecord, key)) entries.push(callbacks.onAdded(key, localValue));
|
|
2721
|
+
else {
|
|
2722
|
+
const entry = callbacks.onModified(key, localValue, remoteRecord[key]);
|
|
2723
|
+
if (entry !== void 0) entries.push(entry);
|
|
2724
|
+
}
|
|
2725
|
+
for (const [key, remoteValue] of Object.entries(remoteRecord)) if (!Object.hasOwn(localRecord, key)) entries.push(callbacks.onDeleted(key, remoteValue));
|
|
2726
|
+
return entries;
|
|
2727
|
+
}
|
|
2728
|
+
|
|
2614
2729
|
//#endregion
|
|
2615
2730
|
//#region src/core/domain/action/services/diffDetector.ts
|
|
2616
2731
|
function compareActions$1(local, remote) {
|
|
2617
2732
|
const diffs = [];
|
|
2618
2733
|
if (local.index !== remote.index) diffs.push(`index: ${remote.index} -> ${local.index}`);
|
|
2619
|
-
if (local.name !== remote.name) diffs.push(`name: "${remote.name}" -> "${local.name}"`);
|
|
2620
2734
|
if (!deepEqual(local.destApp, remote.destApp)) diffs.push("destApp changed");
|
|
2621
2735
|
if (local.filterCond !== remote.filterCond) diffs.push("filterCond changed");
|
|
2622
2736
|
if (!deepEqual(local.mappings, remote.mappings)) if (local.mappings.length !== remote.mappings.length) diffs.push(`mappings: ${remote.mappings.length} -> ${local.mappings.length}`);
|
|
@@ -2624,30 +2738,30 @@ function compareActions$1(local, remote) {
|
|
|
2624
2738
|
if (!deepEqual(local.entities, remote.entities)) diffs.push("entities changed");
|
|
2625
2739
|
return diffs;
|
|
2626
2740
|
}
|
|
2741
|
+
function destAppLabel(action) {
|
|
2742
|
+
return `dest: ${action.destApp.app ?? action.destApp.code ?? "(unspecified)"}`;
|
|
2743
|
+
}
|
|
2627
2744
|
const ActionDiffDetector = { detect: (local, remote) => {
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
const remoteAction = remote.actions[name];
|
|
2631
|
-
if (!remoteAction) entries.push({
|
|
2745
|
+
return buildDiffResult(detectRecordDiff(local.actions, remote.actions, {
|
|
2746
|
+
onAdded: (name, localAction) => ({
|
|
2632
2747
|
type: "added",
|
|
2633
2748
|
actionName: name,
|
|
2634
|
-
details:
|
|
2635
|
-
})
|
|
2636
|
-
|
|
2749
|
+
details: destAppLabel(localAction)
|
|
2750
|
+
}),
|
|
2751
|
+
onModified: (name, localAction, remoteAction) => {
|
|
2637
2752
|
const diffs = compareActions$1(localAction, remoteAction);
|
|
2638
|
-
if (diffs.length > 0)
|
|
2753
|
+
if (diffs.length > 0) return {
|
|
2639
2754
|
type: "modified",
|
|
2640
2755
|
actionName: name,
|
|
2641
2756
|
details: diffs.join(", ")
|
|
2642
|
-
}
|
|
2643
|
-
}
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
});
|
|
2650
|
-
return buildDiffResult(entries);
|
|
2757
|
+
};
|
|
2758
|
+
},
|
|
2759
|
+
onDeleted: (name, remoteAction) => ({
|
|
2760
|
+
type: "deleted",
|
|
2761
|
+
actionName: name,
|
|
2762
|
+
details: destAppLabel(remoteAction)
|
|
2763
|
+
})
|
|
2764
|
+
}));
|
|
2651
2765
|
} };
|
|
2652
2766
|
|
|
2653
2767
|
//#endregion
|
|
@@ -2747,20 +2861,16 @@ var action_default = define({
|
|
|
2747
2861
|
//#endregion
|
|
2748
2862
|
//#region src/core/domain/adminNotes/services/configParser.ts
|
|
2749
2863
|
const AdminNotesConfigParser = { parse: (rawText) => {
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(AdminNotesErrorCode.AnInvalidConfigStructure, "Config must be a YAML object");
|
|
2758
|
-
const obj = parsed;
|
|
2759
|
-
if (typeof obj.content !== "string") throw new BusinessRuleError(AdminNotesErrorCode.AnInvalidConfigStructure, "Config must have a \"content\" string property");
|
|
2760
|
-
if (typeof obj.includeInTemplateAndDuplicates !== "boolean") throw new BusinessRuleError(AdminNotesErrorCode.AnInvalidConfigStructure, "Config must have an \"includeInTemplateAndDuplicates\" boolean property");
|
|
2864
|
+
const parsed = parseYamlConfig(rawText, {
|
|
2865
|
+
emptyConfigText: AdminNotesErrorCode.AnEmptyConfigText,
|
|
2866
|
+
invalidConfigYaml: AdminNotesErrorCode.AnInvalidConfigYaml,
|
|
2867
|
+
invalidConfigStructure: AdminNotesErrorCode.AnInvalidConfigStructure
|
|
2868
|
+
}, "Admin notes");
|
|
2869
|
+
if (typeof parsed.content !== "string") throw new BusinessRuleError(AdminNotesErrorCode.AnInvalidConfigStructure, "Config must have a \"content\" string property");
|
|
2870
|
+
if (typeof parsed.includeInTemplateAndDuplicates !== "boolean") throw new BusinessRuleError(AdminNotesErrorCode.AnInvalidConfigStructure, "Config must have an \"includeInTemplateAndDuplicates\" boolean property");
|
|
2761
2871
|
return {
|
|
2762
|
-
content:
|
|
2763
|
-
includeInTemplateAndDuplicates:
|
|
2872
|
+
content: parsed.content,
|
|
2873
|
+
includeInTemplateAndDuplicates: parsed.includeInTemplateAndDuplicates
|
|
2764
2874
|
};
|
|
2765
2875
|
} };
|
|
2766
2876
|
|
|
@@ -2918,13 +3028,9 @@ var apply_default$11 = define({
|
|
|
2918
3028
|
//#endregion
|
|
2919
3029
|
//#region src/core/domain/adminNotes/services/configSerializer.ts
|
|
2920
3030
|
const AdminNotesConfigSerializer = { serialize: (config) => {
|
|
2921
|
-
return
|
|
3031
|
+
return serializeToYaml({
|
|
2922
3032
|
content: config.content,
|
|
2923
3033
|
includeInTemplateAndDuplicates: config.includeInTemplateAndDuplicates
|
|
2924
|
-
}, {
|
|
2925
|
-
lineWidth: 0,
|
|
2926
|
-
defaultKeyType: "PLAIN",
|
|
2927
|
-
defaultStringType: "PLAIN"
|
|
2928
3034
|
});
|
|
2929
3035
|
} };
|
|
2930
3036
|
|
|
@@ -3048,59 +3154,41 @@ var admin_notes_default = define({
|
|
|
3048
3154
|
|
|
3049
3155
|
//#endregion
|
|
3050
3156
|
//#region src/core/domain/appPermission/services/configParser.ts
|
|
3051
|
-
const VALID_ENTITY_TYPES$
|
|
3157
|
+
const VALID_ENTITY_TYPES$8 = new Set([
|
|
3052
3158
|
"USER",
|
|
3053
3159
|
"GROUP",
|
|
3054
3160
|
"ORGANIZATION",
|
|
3055
3161
|
"CREATOR"
|
|
3056
3162
|
]);
|
|
3057
3163
|
function parseEntity$3(raw, index) {
|
|
3058
|
-
|
|
3059
|
-
|
|
3060
|
-
|
|
3061
|
-
|
|
3062
|
-
|
|
3063
|
-
type,
|
|
3064
|
-
code: typeof obj.code === "string" ? obj.code : ""
|
|
3065
|
-
};
|
|
3066
|
-
if (typeof obj.code !== "string" || obj.code.length === 0) throw new BusinessRuleError(AppPermissionErrorCode.ApEmptyEntityCode, `Entity at index ${index} must have a non-empty "code" property`);
|
|
3067
|
-
return {
|
|
3068
|
-
type,
|
|
3069
|
-
code: obj.code
|
|
3070
|
-
};
|
|
3071
|
-
}
|
|
3072
|
-
function parseBooleanField$1(obj, field, index) {
|
|
3073
|
-
const value = obj[field];
|
|
3074
|
-
if (typeof value !== "boolean") throw new BusinessRuleError(AppPermissionErrorCode.ApInvalidBooleanField, `App right at index ${index} must have a boolean "${field}" property`);
|
|
3075
|
-
return value;
|
|
3164
|
+
return parseEntityBase(raw, index, VALID_ENTITY_TYPES$8, {
|
|
3165
|
+
invalidStructure: AppPermissionErrorCode.ApInvalidConfigStructure,
|
|
3166
|
+
invalidType: AppPermissionErrorCode.ApInvalidEntityType,
|
|
3167
|
+
emptyCode: AppPermissionErrorCode.ApEmptyEntityCode
|
|
3168
|
+
}, { allowEmptyCode: (type) => type === "CREATOR" });
|
|
3076
3169
|
}
|
|
3077
3170
|
function parseAppRight(raw, index) {
|
|
3078
3171
|
if (!isRecord(raw)) throw new BusinessRuleError(AppPermissionErrorCode.ApInvalidConfigStructure, `App right at index ${index} must be an object`);
|
|
3079
|
-
const obj = raw;
|
|
3080
3172
|
return {
|
|
3081
|
-
entity: parseEntity$3(
|
|
3082
|
-
includeSubs:
|
|
3083
|
-
appEditable:
|
|
3084
|
-
recordViewable:
|
|
3085
|
-
recordAddable:
|
|
3086
|
-
recordEditable:
|
|
3087
|
-
recordDeletable:
|
|
3088
|
-
recordImportable:
|
|
3089
|
-
recordExportable:
|
|
3173
|
+
entity: parseEntity$3(raw.entity, index),
|
|
3174
|
+
includeSubs: parseStrictBoolean(raw.includeSubs, "includeSubs", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3175
|
+
appEditable: parseStrictBoolean(raw.appEditable, "appEditable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3176
|
+
recordViewable: parseStrictBoolean(raw.recordViewable, "recordViewable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3177
|
+
recordAddable: parseStrictBoolean(raw.recordAddable, "recordAddable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3178
|
+
recordEditable: parseStrictBoolean(raw.recordEditable, "recordEditable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3179
|
+
recordDeletable: parseStrictBoolean(raw.recordDeletable, "recordDeletable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3180
|
+
recordImportable: parseStrictBoolean(raw.recordImportable, "recordImportable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField),
|
|
3181
|
+
recordExportable: parseStrictBoolean(raw.recordExportable, "recordExportable", `App right at index ${index}`, AppPermissionErrorCode.ApInvalidBooleanField)
|
|
3090
3182
|
};
|
|
3091
3183
|
}
|
|
3092
3184
|
const AppPermissionConfigParser = { parse: (rawText) => {
|
|
3093
|
-
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3097
|
-
}
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(AppPermissionErrorCode.ApInvalidConfigStructure, "Config must be a YAML object");
|
|
3101
|
-
const obj = parsed;
|
|
3102
|
-
if (!Array.isArray(obj.rights)) throw new BusinessRuleError(AppPermissionErrorCode.ApInvalidConfigStructure, "Config must have a \"rights\" array");
|
|
3103
|
-
const rights = obj.rights.map((item, i) => parseAppRight(item, i));
|
|
3185
|
+
const parsed = parseYamlConfig(rawText, {
|
|
3186
|
+
emptyConfigText: AppPermissionErrorCode.ApEmptyConfigText,
|
|
3187
|
+
invalidConfigYaml: AppPermissionErrorCode.ApInvalidConfigYaml,
|
|
3188
|
+
invalidConfigStructure: AppPermissionErrorCode.ApInvalidConfigStructure
|
|
3189
|
+
}, "App permission");
|
|
3190
|
+
if (!Array.isArray(parsed.rights)) throw new BusinessRuleError(AppPermissionErrorCode.ApInvalidConfigStructure, "Config must have a \"rights\" array");
|
|
3191
|
+
const rights = parsed.rights.map((item, i) => parseAppRight(item, i));
|
|
3104
3192
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
3105
3193
|
for (const right of rights) {
|
|
3106
3194
|
const key = `${right.entity.type}:${right.entity.code}`;
|
|
@@ -3131,14 +3219,14 @@ async function applyAppPermission({ container }) {
|
|
|
3131
3219
|
|
|
3132
3220
|
//#endregion
|
|
3133
3221
|
//#region src/core/adapters/kintone/appPermissionConfigurator.ts
|
|
3134
|
-
const VALID_ENTITY_TYPES$
|
|
3222
|
+
const VALID_ENTITY_TYPES$7 = new Set([
|
|
3135
3223
|
"USER",
|
|
3136
3224
|
"GROUP",
|
|
3137
3225
|
"ORGANIZATION",
|
|
3138
3226
|
"CREATOR"
|
|
3139
3227
|
]);
|
|
3140
3228
|
function fromKintoneRight$2(raw) {
|
|
3141
|
-
if (!VALID_ENTITY_TYPES$
|
|
3229
|
+
if (!VALID_ENTITY_TYPES$7.has(raw.entity.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected entity type from kintone API: ${raw.entity.type}`);
|
|
3142
3230
|
const type = raw.entity.type;
|
|
3143
3231
|
let code;
|
|
3144
3232
|
if (type === "CREATOR") code = raw.entity.code ?? "";
|
|
@@ -3322,11 +3410,7 @@ function serializeAppRight(right) {
|
|
|
3322
3410
|
};
|
|
3323
3411
|
}
|
|
3324
3412
|
const AppPermissionConfigSerializer = { serialize: (config) => {
|
|
3325
|
-
return
|
|
3326
|
-
lineWidth: 0,
|
|
3327
|
-
defaultKeyType: "PLAIN",
|
|
3328
|
-
defaultStringType: "PLAIN"
|
|
3329
|
-
});
|
|
3413
|
+
return serializeToYaml({ rights: config.rights.map(serializeAppRight) });
|
|
3330
3414
|
} };
|
|
3331
3415
|
|
|
3332
3416
|
//#endregion
|
|
@@ -3509,28 +3593,21 @@ const ResourceMerger = {
|
|
|
3509
3593
|
|
|
3510
3594
|
//#endregion
|
|
3511
3595
|
//#region src/core/domain/customization/services/configParser.ts
|
|
3512
|
-
const VALID_SCOPES = new Set([
|
|
3513
|
-
"ALL",
|
|
3514
|
-
"ADMIN",
|
|
3515
|
-
"NONE"
|
|
3516
|
-
]);
|
|
3517
|
-
const VALID_RESOURCE_TYPES = new Set(["FILE", "URL"]);
|
|
3518
3596
|
function parseResource(raw, index) {
|
|
3519
3597
|
if (!isRecord(raw)) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidConfigStructure, `Resource at index ${index} must be an object`);
|
|
3520
|
-
const
|
|
3521
|
-
|
|
3522
|
-
if (typeof type !== "string" || !VALID_RESOURCE_TYPES.has(type)) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidResourceType, `Resource at index ${index} has invalid type: ${String(type)}. Must be FILE or URL`);
|
|
3598
|
+
const type = raw.type;
|
|
3599
|
+
if (typeof type !== "string" || !isResourceType(type)) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidResourceType, `Resource at index ${index} has invalid type: ${String(type)}. Must be FILE or URL`);
|
|
3523
3600
|
if (type === "FILE") {
|
|
3524
|
-
if (typeof
|
|
3601
|
+
if (typeof raw.path !== "string" || raw.path.length === 0) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidConfigStructure, `FILE resource at index ${index} must have a non-empty "path" property`);
|
|
3525
3602
|
return {
|
|
3526
3603
|
type: "FILE",
|
|
3527
|
-
path:
|
|
3604
|
+
path: raw.path
|
|
3528
3605
|
};
|
|
3529
3606
|
}
|
|
3530
|
-
if (typeof
|
|
3607
|
+
if (typeof raw.url !== "string" || raw.url.length === 0) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidConfigStructure, `URL resource at index ${index} must have a non-empty "url" property`);
|
|
3531
3608
|
return {
|
|
3532
3609
|
type: "URL",
|
|
3533
|
-
url:
|
|
3610
|
+
url: raw.url
|
|
3534
3611
|
};
|
|
3535
3612
|
}
|
|
3536
3613
|
function parseResourceList(raw) {
|
|
@@ -3539,25 +3616,20 @@ function parseResourceList(raw) {
|
|
|
3539
3616
|
}
|
|
3540
3617
|
function parsePlatform(raw) {
|
|
3541
3618
|
if (!isRecord(raw)) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidConfigStructure, "Platform configuration must be an object");
|
|
3542
|
-
const obj = raw;
|
|
3543
3619
|
return {
|
|
3544
|
-
js:
|
|
3545
|
-
css:
|
|
3620
|
+
js: raw.js === void 0 || raw.js === null ? [] : parseResourceList(raw.js),
|
|
3621
|
+
css: raw.css === void 0 || raw.css === null ? [] : parseResourceList(raw.css)
|
|
3546
3622
|
};
|
|
3547
3623
|
}
|
|
3548
|
-
const
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
}
|
|
3554
|
-
throw new BusinessRuleError(CustomizationErrorCode.CzInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
3555
|
-
}
|
|
3556
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidConfigStructure, "Config must be a YAML object");
|
|
3557
|
-
const obj = parsed;
|
|
3624
|
+
const CustomizationConfigParser = { parse: (rawText) => {
|
|
3625
|
+
const obj = parseYamlConfig(rawText, {
|
|
3626
|
+
emptyConfigText: CustomizationErrorCode.CzEmptyConfigText,
|
|
3627
|
+
invalidConfigYaml: CustomizationErrorCode.CzInvalidConfigYaml,
|
|
3628
|
+
invalidConfigStructure: CustomizationErrorCode.CzInvalidConfigStructure
|
|
3629
|
+
}, "Customization");
|
|
3558
3630
|
let scope;
|
|
3559
3631
|
if (obj.scope !== void 0 && obj.scope !== null) {
|
|
3560
|
-
if (typeof obj.scope !== "string" || !
|
|
3632
|
+
if (typeof obj.scope !== "string" || !isCustomizationScope(obj.scope)) throw new BusinessRuleError(CustomizationErrorCode.CzInvalidScope, `Invalid scope: ${String(obj.scope)}. Must be ALL, ADMIN, or NONE`);
|
|
3561
3633
|
scope = obj.scope;
|
|
3562
3634
|
}
|
|
3563
3635
|
const desktop = obj.desktop === void 0 || obj.desktop === null ? {
|
|
@@ -3578,7 +3650,7 @@ const ConfigParser = { parse: (rawText) => {
|
|
|
3578
3650
|
//#endregion
|
|
3579
3651
|
//#region src/core/application/customization/parseConfig.ts
|
|
3580
3652
|
function parseConfigText(rawText) {
|
|
3581
|
-
return wrapBusinessRuleError(() =>
|
|
3653
|
+
return wrapBusinessRuleError(() => CustomizationConfigParser.parse(rawText));
|
|
3582
3654
|
}
|
|
3583
3655
|
|
|
3584
3656
|
//#endregion
|
|
@@ -3681,14 +3753,10 @@ function serializePlatform(platform) {
|
|
|
3681
3753
|
};
|
|
3682
3754
|
}
|
|
3683
3755
|
const CustomizationConfigSerializer = { serialize: (config) => {
|
|
3684
|
-
return
|
|
3756
|
+
return serializeToYaml({
|
|
3685
3757
|
...config.scope !== void 0 ? { scope: config.scope } : {},
|
|
3686
3758
|
...hasPlatformResources(config.desktop) ? { desktop: serializePlatform(config.desktop) } : {},
|
|
3687
3759
|
...hasPlatformResources(config.mobile) ? { mobile: serializePlatform(config.mobile) } : {}
|
|
3688
|
-
}, {
|
|
3689
|
-
lineWidth: 0,
|
|
3690
|
-
defaultKeyType: "PLAIN",
|
|
3691
|
-
defaultStringType: "PLAIN"
|
|
3692
3760
|
});
|
|
3693
3761
|
} };
|
|
3694
3762
|
|
|
@@ -3950,15 +4018,11 @@ var apply_default$9 = define({
|
|
|
3950
4018
|
}
|
|
3951
4019
|
});
|
|
3952
4020
|
|
|
3953
|
-
//#endregion
|
|
3954
|
-
//#region src/core/domain/customization/valueObject.ts
|
|
3955
|
-
const DEFAULT_CUSTOMIZATION_SCOPE = "ALL";
|
|
3956
|
-
|
|
3957
4021
|
//#endregion
|
|
3958
4022
|
//#region src/core/domain/customization/services/diffDetector.ts
|
|
3959
4023
|
function resourceName(resource) {
|
|
3960
4024
|
if (resource.type === "URL") return resource.url;
|
|
3961
|
-
const parts = resource.path.replace(/\\/g, "/").split("/");
|
|
4025
|
+
const parts = resource.path.replace(/\\/g, "/").split("/").filter(Boolean);
|
|
3962
4026
|
return parts[parts.length - 1];
|
|
3963
4027
|
}
|
|
3964
4028
|
function remoteResourceName(resource) {
|
|
@@ -4069,7 +4133,7 @@ const VALID_ACCESSIBILITIES$1 = new Set([
|
|
|
4069
4133
|
"WRITE",
|
|
4070
4134
|
"NONE"
|
|
4071
4135
|
]);
|
|
4072
|
-
const VALID_ENTITY_TYPES$
|
|
4136
|
+
const VALID_ENTITY_TYPES$6 = new Set([
|
|
4073
4137
|
"USER",
|
|
4074
4138
|
"GROUP",
|
|
4075
4139
|
"ORGANIZATION",
|
|
@@ -4077,7 +4141,7 @@ const VALID_ENTITY_TYPES$7 = new Set([
|
|
|
4077
4141
|
]);
|
|
4078
4142
|
function fromKintoneEntity$3(raw) {
|
|
4079
4143
|
if (!VALID_ACCESSIBILITIES$1.has(raw.accessibility)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected accessibility value from kintone API: ${raw.accessibility}`);
|
|
4080
|
-
if (!VALID_ENTITY_TYPES$
|
|
4144
|
+
if (!VALID_ENTITY_TYPES$6.has(raw.entity.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected entity type from kintone API: ${raw.entity.type}`);
|
|
4081
4145
|
const result = {
|
|
4082
4146
|
accessibility: raw.accessibility,
|
|
4083
4147
|
entity: {
|
|
@@ -4179,60 +4243,49 @@ const VALID_ACCESSIBILITIES = new Set([
|
|
|
4179
4243
|
"WRITE",
|
|
4180
4244
|
"NONE"
|
|
4181
4245
|
]);
|
|
4182
|
-
const VALID_ENTITY_TYPES$
|
|
4246
|
+
const VALID_ENTITY_TYPES$5 = new Set([
|
|
4183
4247
|
"USER",
|
|
4184
4248
|
"GROUP",
|
|
4185
4249
|
"ORGANIZATION",
|
|
4186
4250
|
"FIELD_ENTITY"
|
|
4187
4251
|
]);
|
|
4188
4252
|
function parseEntity$2(raw, index) {
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
type: obj.type,
|
|
4195
|
-
code: obj.code
|
|
4196
|
-
};
|
|
4253
|
+
return parseEntityBase(raw, index, VALID_ENTITY_TYPES$5, {
|
|
4254
|
+
invalidStructure: FieldPermissionErrorCode.FpInvalidConfigStructure,
|
|
4255
|
+
invalidType: FieldPermissionErrorCode.FpInvalidEntityType,
|
|
4256
|
+
emptyCode: FieldPermissionErrorCode.FpEmptyEntityCode
|
|
4257
|
+
});
|
|
4197
4258
|
}
|
|
4198
4259
|
function parseFieldRightEntity(raw, index) {
|
|
4199
4260
|
if (!isRecord(raw)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidConfigStructure, `Field right entity at index ${index} must be an object`);
|
|
4200
|
-
const obj = raw;
|
|
4201
|
-
if (typeof obj.accessibility !== "string" || !VALID_ACCESSIBILITIES.has(obj.accessibility)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidAccessibility, `Field right entity at index ${index} has invalid accessibility: ${String(obj.accessibility)}. Must be READ, WRITE, or NONE`);
|
|
4202
|
-
const entity = parseEntity$2(obj.entity, index);
|
|
4203
4261
|
const result = {
|
|
4204
|
-
accessibility:
|
|
4205
|
-
entity
|
|
4262
|
+
accessibility: parseEnum(raw.accessibility, VALID_ACCESSIBILITIES, FieldPermissionErrorCode.FpInvalidAccessibility, `Field right entity at index ${index} has invalid accessibility: ${String(raw.accessibility)}. Must be READ, WRITE, or NONE`),
|
|
4263
|
+
entity: parseEntity$2(raw.entity, index)
|
|
4206
4264
|
};
|
|
4207
|
-
if (
|
|
4265
|
+
if (raw.includeSubs !== void 0 && raw.includeSubs !== null) return {
|
|
4208
4266
|
...result,
|
|
4209
|
-
includeSubs:
|
|
4267
|
+
includeSubs: parseStrictBoolean(raw.includeSubs, "includeSubs", `Field right entity at index ${index}`, FieldPermissionErrorCode.FpInvalidBooleanField)
|
|
4210
4268
|
};
|
|
4211
4269
|
return result;
|
|
4212
4270
|
}
|
|
4213
4271
|
function parseFieldRight(raw, index) {
|
|
4214
4272
|
if (!isRecord(raw)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidConfigStructure, `Field right at index ${index} must be an object`);
|
|
4215
|
-
|
|
4216
|
-
if (
|
|
4217
|
-
|
|
4218
|
-
const entities = obj.entities.map((item, i) => parseFieldRightEntity(item, i));
|
|
4273
|
+
if (typeof raw.code !== "string" || raw.code.length === 0) throw new BusinessRuleError(FieldPermissionErrorCode.FpEmptyFieldCode, `Field right at index ${index} must have a non-empty "code" property`);
|
|
4274
|
+
if (!Array.isArray(raw.entities)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidConfigStructure, `Field right at index ${index} must have an "entities" array`);
|
|
4275
|
+
const entities = raw.entities.map((item, i) => parseFieldRightEntity(item, i));
|
|
4219
4276
|
return {
|
|
4220
|
-
code:
|
|
4277
|
+
code: raw.code,
|
|
4221
4278
|
entities
|
|
4222
4279
|
};
|
|
4223
4280
|
}
|
|
4224
4281
|
const FieldPermissionConfigParser = { parse: (rawText) => {
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
}
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidConfigStructure, "Config must be a YAML object");
|
|
4233
|
-
const obj = parsed;
|
|
4234
|
-
if (!Array.isArray(obj.rights)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidConfigStructure, "Config must have a \"rights\" array");
|
|
4235
|
-
const rights = obj.rights.map((item, i) => parseFieldRight(item, i));
|
|
4282
|
+
const parsed = parseYamlConfig(rawText, {
|
|
4283
|
+
emptyConfigText: FieldPermissionErrorCode.FpEmptyConfigText,
|
|
4284
|
+
invalidConfigYaml: FieldPermissionErrorCode.FpInvalidConfigYaml,
|
|
4285
|
+
invalidConfigStructure: FieldPermissionErrorCode.FpInvalidConfigStructure
|
|
4286
|
+
}, "Field permission");
|
|
4287
|
+
if (!Array.isArray(parsed.rights)) throw new BusinessRuleError(FieldPermissionErrorCode.FpInvalidConfigStructure, "Config must have a \"rights\" array");
|
|
4288
|
+
const rights = parsed.rights.map((item, i) => parseFieldRight(item, i));
|
|
4236
4289
|
const seenCodes = /* @__PURE__ */ new Set();
|
|
4237
4290
|
for (const right of rights) {
|
|
4238
4291
|
if (seenCodes.has(right.code)) throw new BusinessRuleError(FieldPermissionErrorCode.FpDuplicateFieldCode, `Duplicate field code: ${right.code}`);
|
|
@@ -4342,14 +4395,10 @@ function serializeFieldRightEntity(entity) {
|
|
|
4342
4395
|
return result;
|
|
4343
4396
|
}
|
|
4344
4397
|
const FieldPermissionConfigSerializer = { serialize: (config) => {
|
|
4345
|
-
return
|
|
4398
|
+
return serializeToYaml({ rights: config.rights.map((right) => ({
|
|
4346
4399
|
code: right.code,
|
|
4347
4400
|
entities: right.entities.map(serializeFieldRightEntity)
|
|
4348
|
-
})) }
|
|
4349
|
-
lineWidth: 0,
|
|
4350
|
-
defaultKeyType: "PLAIN",
|
|
4351
|
-
defaultStringType: "PLAIN"
|
|
4352
|
-
});
|
|
4401
|
+
})) });
|
|
4353
4402
|
} };
|
|
4354
4403
|
|
|
4355
4404
|
//#endregion
|
|
@@ -4413,7 +4462,7 @@ var capture_default$9 = define({
|
|
|
4413
4462
|
|
|
4414
4463
|
//#endregion
|
|
4415
4464
|
//#region src/core/domain/fieldPermission/services/diffDetector.ts
|
|
4416
|
-
function
|
|
4465
|
+
function isEntitiesEqual$1(a, b) {
|
|
4417
4466
|
return deepEqual(a.entities.map((e) => ({
|
|
4418
4467
|
accessibility: e.accessibility,
|
|
4419
4468
|
type: e.entity.type,
|
|
@@ -4437,7 +4486,7 @@ const FieldPermissionDiffDetector = { detect: (local, remote) => {
|
|
|
4437
4486
|
fieldCode: code,
|
|
4438
4487
|
details: `${localRight.entities.length} entities`
|
|
4439
4488
|
});
|
|
4440
|
-
else if (!
|
|
4489
|
+
else if (!isEntitiesEqual$1(localRight, remoteRight)) entries.push({
|
|
4441
4490
|
type: "modified",
|
|
4442
4491
|
fieldCode: code,
|
|
4443
4492
|
details: "entities changed"
|
|
@@ -4649,18 +4698,22 @@ function createGeneralSettingsCliContainer(config) {
|
|
|
4649
4698
|
}
|
|
4650
4699
|
|
|
4651
4700
|
//#endregion
|
|
4652
|
-
//#region src/core/
|
|
4653
|
-
const
|
|
4701
|
+
//#region src/core/domain/notification/valueObject.ts
|
|
4702
|
+
const ENTITY_TYPES = [
|
|
4654
4703
|
"USER",
|
|
4655
4704
|
"GROUP",
|
|
4656
4705
|
"ORGANIZATION",
|
|
4657
4706
|
"FIELD_ENTITY"
|
|
4658
|
-
]
|
|
4659
|
-
|
|
4660
|
-
|
|
4707
|
+
];
|
|
4708
|
+
const VALID_ENTITY_TYPES$4 = new Set(ENTITY_TYPES);
|
|
4709
|
+
function isNotificationEntityType(value) {
|
|
4710
|
+
return VALID_ENTITY_TYPES$4.has(value);
|
|
4661
4711
|
}
|
|
4712
|
+
|
|
4713
|
+
//#endregion
|
|
4714
|
+
//#region src/core/adapters/kintone/notificationConfigurator.ts
|
|
4662
4715
|
function fromKintoneEntity$2(raw) {
|
|
4663
|
-
|
|
4716
|
+
if (!isNotificationEntityType(raw.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected entity type from kintone API (entity): ${raw.type}`);
|
|
4664
4717
|
return {
|
|
4665
4718
|
type: raw.type,
|
|
4666
4719
|
code: raw.code
|
|
@@ -4681,7 +4734,7 @@ function fromKintoneGeneralNotification(raw) {
|
|
|
4681
4734
|
};
|
|
4682
4735
|
return result;
|
|
4683
4736
|
}
|
|
4684
|
-
function
|
|
4737
|
+
function fromKintoneTarget(raw) {
|
|
4685
4738
|
const result = { entity: fromKintoneEntity$2(raw.entity) };
|
|
4686
4739
|
if (raw.includeSubs !== void 0) return {
|
|
4687
4740
|
...result,
|
|
@@ -4693,29 +4746,27 @@ function fromKintonePerRecordNotification(raw) {
|
|
|
4693
4746
|
return {
|
|
4694
4747
|
filterCond: raw.filterCond,
|
|
4695
4748
|
title: raw.title,
|
|
4696
|
-
targets: raw.targets.map(
|
|
4697
|
-
};
|
|
4698
|
-
}
|
|
4699
|
-
function fromKintoneReminderTarget(raw) {
|
|
4700
|
-
const result = { entity: fromKintoneEntity$2(raw.entity) };
|
|
4701
|
-
if (raw.includeSubs !== void 0) return {
|
|
4702
|
-
...result,
|
|
4703
|
-
includeSubs: raw.includeSubs
|
|
4749
|
+
targets: raw.targets.map(fromKintoneTarget)
|
|
4704
4750
|
};
|
|
4705
|
-
return result;
|
|
4706
4751
|
}
|
|
4707
4752
|
function fromKintoneReminderNotification(raw) {
|
|
4753
|
+
const daysLater = Number(raw.timing.daysLater);
|
|
4754
|
+
if (!Number.isFinite(daysLater)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected non-numeric daysLater from kintone API: ${raw.timing.daysLater}`);
|
|
4708
4755
|
const result = {
|
|
4709
4756
|
code: raw.timing.code,
|
|
4710
|
-
daysLater
|
|
4757
|
+
daysLater,
|
|
4711
4758
|
filterCond: raw.filterCond,
|
|
4712
4759
|
title: raw.title,
|
|
4713
|
-
targets: raw.targets.map(
|
|
4714
|
-
};
|
|
4715
|
-
if ("hoursLater" in raw.timing) return {
|
|
4716
|
-
...result,
|
|
4717
|
-
hoursLater: Number(raw.timing.hoursLater)
|
|
4760
|
+
targets: raw.targets.map(fromKintoneTarget)
|
|
4718
4761
|
};
|
|
4762
|
+
if ("hoursLater" in raw.timing) {
|
|
4763
|
+
const hoursLater = Number(raw.timing.hoursLater);
|
|
4764
|
+
if (!Number.isFinite(hoursLater)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected non-numeric hoursLater from kintone API: ${raw.timing.hoursLater}`);
|
|
4765
|
+
return {
|
|
4766
|
+
...result,
|
|
4767
|
+
hoursLater
|
|
4768
|
+
};
|
|
4769
|
+
}
|
|
4719
4770
|
if ("time" in raw.timing) return {
|
|
4720
4771
|
...result,
|
|
4721
4772
|
time: raw.timing.time
|
|
@@ -4740,7 +4791,7 @@ function toKintoneGeneralNotification(notification) {
|
|
|
4740
4791
|
if (notification.includeSubs !== void 0) result.includeSubs = notification.includeSubs;
|
|
4741
4792
|
return result;
|
|
4742
4793
|
}
|
|
4743
|
-
function
|
|
4794
|
+
function toKintoneTarget(target) {
|
|
4744
4795
|
const result = { entity: toKintoneEntity$2(target.entity) };
|
|
4745
4796
|
if (target.includeSubs !== void 0) result.includeSubs = target.includeSubs;
|
|
4746
4797
|
return result;
|
|
@@ -4749,14 +4800,9 @@ function toKintonePerRecordNotification(notification) {
|
|
|
4749
4800
|
return {
|
|
4750
4801
|
filterCond: notification.filterCond,
|
|
4751
4802
|
title: notification.title,
|
|
4752
|
-
targets: notification.targets.map(
|
|
4803
|
+
targets: notification.targets.map(toKintoneTarget)
|
|
4753
4804
|
};
|
|
4754
4805
|
}
|
|
4755
|
-
function toKintoneReminderTarget(target) {
|
|
4756
|
-
const result = { entity: toKintoneEntity$2(target.entity) };
|
|
4757
|
-
if (target.includeSubs !== void 0) result.includeSubs = target.includeSubs;
|
|
4758
|
-
return result;
|
|
4759
|
-
}
|
|
4760
4806
|
function toKintoneReminderNotification(notification) {
|
|
4761
4807
|
if (notification.hoursLater !== void 0 && notification.time !== void 0) throw new SystemError(SystemErrorCode.ExternalApiError, `Reminder notification "${notification.code}" must not have both "hoursLater" and "time"`);
|
|
4762
4808
|
const timing = {
|
|
@@ -4769,7 +4815,7 @@ function toKintoneReminderNotification(notification) {
|
|
|
4769
4815
|
timing,
|
|
4770
4816
|
filterCond: notification.filterCond,
|
|
4771
4817
|
title: notification.title,
|
|
4772
|
-
targets: notification.targets.map(
|
|
4818
|
+
targets: notification.targets.map(toKintoneTarget)
|
|
4773
4819
|
};
|
|
4774
4820
|
}
|
|
4775
4821
|
var KintoneNotificationConfigurator = class {
|
|
@@ -4966,7 +5012,7 @@ const VALID_ASSIGNEE_TYPES$1 = new Set([
|
|
|
4966
5012
|
"ALL",
|
|
4967
5013
|
"ANY"
|
|
4968
5014
|
]);
|
|
4969
|
-
const VALID_ENTITY_TYPES$
|
|
5015
|
+
const VALID_ENTITY_TYPES$3 = new Set([
|
|
4970
5016
|
"USER",
|
|
4971
5017
|
"GROUP",
|
|
4972
5018
|
"ORGANIZATION",
|
|
@@ -4976,7 +5022,7 @@ const VALID_ENTITY_TYPES$4 = new Set([
|
|
|
4976
5022
|
]);
|
|
4977
5023
|
const VALID_ACTION_TYPES$1 = new Set(["PRIMARY", "SECONDARY"]);
|
|
4978
5024
|
function fromKintoneEntity$1(raw) {
|
|
4979
|
-
if (!VALID_ENTITY_TYPES$
|
|
5025
|
+
if (!VALID_ENTITY_TYPES$3.has(raw.entity.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected entity type from kintone API: ${raw.entity.type}`);
|
|
4980
5026
|
const result = { type: raw.entity.type };
|
|
4981
5027
|
const withCode = raw.entity.code !== void 0 ? {
|
|
4982
5028
|
...result,
|
|
@@ -5118,14 +5164,14 @@ function createProcessManagementCliContainer(config) {
|
|
|
5118
5164
|
|
|
5119
5165
|
//#endregion
|
|
5120
5166
|
//#region src/core/adapters/kintone/recordPermissionConfigurator.ts
|
|
5121
|
-
const VALID_ENTITY_TYPES$
|
|
5167
|
+
const VALID_ENTITY_TYPES$2 = new Set([
|
|
5122
5168
|
"USER",
|
|
5123
5169
|
"GROUP",
|
|
5124
5170
|
"ORGANIZATION",
|
|
5125
5171
|
"FIELD_ENTITY"
|
|
5126
5172
|
]);
|
|
5127
5173
|
function fromKintoneEntity(raw) {
|
|
5128
|
-
if (!VALID_ENTITY_TYPES$
|
|
5174
|
+
if (!VALID_ENTITY_TYPES$2.has(raw.entity.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected entity type from kintone API: ${raw.entity.type}`);
|
|
5129
5175
|
return {
|
|
5130
5176
|
entity: {
|
|
5131
5177
|
type: raw.entity.type,
|
|
@@ -5220,8 +5266,8 @@ function createRecordPermissionCliContainer(config) {
|
|
|
5220
5266
|
}
|
|
5221
5267
|
|
|
5222
5268
|
//#endregion
|
|
5223
|
-
//#region src/core/
|
|
5224
|
-
const
|
|
5269
|
+
//#region src/core/domain/report/valueObject.ts
|
|
5270
|
+
const CHART_TYPES = [
|
|
5225
5271
|
"BAR",
|
|
5226
5272
|
"COLUMN",
|
|
5227
5273
|
"PIE",
|
|
@@ -5231,13 +5277,21 @@ const VALID_CHART_TYPES$1 = new Set([
|
|
|
5231
5277
|
"AREA",
|
|
5232
5278
|
"SPLINE",
|
|
5233
5279
|
"SPLINE_AREA"
|
|
5234
|
-
]
|
|
5235
|
-
const
|
|
5280
|
+
];
|
|
5281
|
+
const VALID_CHART_TYPES = new Set(CHART_TYPES);
|
|
5282
|
+
function isChartType(value) {
|
|
5283
|
+
return VALID_CHART_TYPES.has(value);
|
|
5284
|
+
}
|
|
5285
|
+
const CHART_MODES = [
|
|
5236
5286
|
"NORMAL",
|
|
5237
5287
|
"STACKED",
|
|
5238
5288
|
"PERCENTAGE"
|
|
5239
|
-
]
|
|
5240
|
-
const
|
|
5289
|
+
];
|
|
5290
|
+
const VALID_CHART_MODES = new Set(CHART_MODES);
|
|
5291
|
+
function isChartMode(value) {
|
|
5292
|
+
return VALID_CHART_MODES.has(value);
|
|
5293
|
+
}
|
|
5294
|
+
const GROUP_PERS = [
|
|
5241
5295
|
"YEAR",
|
|
5242
5296
|
"QUARTER",
|
|
5243
5297
|
"MONTH",
|
|
@@ -5245,38 +5299,78 @@ const VALID_GROUP_PERS = new Set([
|
|
|
5245
5299
|
"DAY",
|
|
5246
5300
|
"HOUR",
|
|
5247
5301
|
"MINUTE"
|
|
5248
|
-
]
|
|
5249
|
-
const
|
|
5302
|
+
];
|
|
5303
|
+
const VALID_GROUP_PERS = new Set(GROUP_PERS);
|
|
5304
|
+
function isGroupPer(value) {
|
|
5305
|
+
return VALID_GROUP_PERS.has(value);
|
|
5306
|
+
}
|
|
5307
|
+
const AGGREGATION_TYPES = [
|
|
5250
5308
|
"COUNT",
|
|
5251
5309
|
"SUM",
|
|
5252
5310
|
"AVERAGE",
|
|
5253
5311
|
"MAX",
|
|
5254
5312
|
"MIN"
|
|
5255
|
-
]
|
|
5256
|
-
const
|
|
5313
|
+
];
|
|
5314
|
+
const VALID_AGGREGATION_TYPES = new Set(AGGREGATION_TYPES);
|
|
5315
|
+
function isAggregationType(value) {
|
|
5316
|
+
return VALID_AGGREGATION_TYPES.has(value);
|
|
5317
|
+
}
|
|
5318
|
+
const SORT_BYS = [
|
|
5257
5319
|
"TOTAL",
|
|
5258
5320
|
"GROUP1",
|
|
5259
5321
|
"GROUP2",
|
|
5260
5322
|
"GROUP3"
|
|
5261
|
-
]
|
|
5262
|
-
const
|
|
5263
|
-
|
|
5323
|
+
];
|
|
5324
|
+
const VALID_SORT_BYS = new Set(SORT_BYS);
|
|
5325
|
+
function isSortBy(value) {
|
|
5326
|
+
return VALID_SORT_BYS.has(value);
|
|
5327
|
+
}
|
|
5328
|
+
const SORT_ORDERS = ["ASC", "DESC"];
|
|
5329
|
+
const VALID_SORT_ORDERS = new Set(SORT_ORDERS);
|
|
5330
|
+
function isSortOrder(value) {
|
|
5331
|
+
return VALID_SORT_ORDERS.has(value);
|
|
5332
|
+
}
|
|
5333
|
+
const PERIODIC_REPORT_EVERYS = [
|
|
5264
5334
|
"YEAR",
|
|
5265
5335
|
"QUARTER",
|
|
5266
5336
|
"MONTH",
|
|
5267
5337
|
"WEEK",
|
|
5268
5338
|
"DAY",
|
|
5269
5339
|
"HOUR"
|
|
5270
|
-
]
|
|
5271
|
-
const
|
|
5340
|
+
];
|
|
5341
|
+
const VALID_PERIODIC_REPORT_EVERYS = new Set(PERIODIC_REPORT_EVERYS);
|
|
5342
|
+
function isPeriodicReportEvery(value) {
|
|
5343
|
+
return VALID_PERIODIC_REPORT_EVERYS.has(value);
|
|
5344
|
+
}
|
|
5345
|
+
const PERIODIC_REPORT_PATTERNS = [
|
|
5272
5346
|
"JAN_APR_JUL_OCT",
|
|
5273
5347
|
"FEB_MAY_AUG_NOV",
|
|
5274
5348
|
"MAR_JUN_SEP_DEC"
|
|
5275
|
-
]
|
|
5349
|
+
];
|
|
5350
|
+
const VALID_PERIODIC_REPORT_PATTERNS = new Set(PERIODIC_REPORT_PATTERNS);
|
|
5351
|
+
function isPeriodicReportPattern(value) {
|
|
5352
|
+
return VALID_PERIODIC_REPORT_PATTERNS.has(value);
|
|
5353
|
+
}
|
|
5354
|
+
const DAYS_OF_WEEK = [
|
|
5355
|
+
"SUNDAY",
|
|
5356
|
+
"MONDAY",
|
|
5357
|
+
"TUESDAY",
|
|
5358
|
+
"WEDNESDAY",
|
|
5359
|
+
"THURSDAY",
|
|
5360
|
+
"FRIDAY",
|
|
5361
|
+
"SATURDAY"
|
|
5362
|
+
];
|
|
5363
|
+
const VALID_DAYS_OF_WEEK = new Set(DAYS_OF_WEEK);
|
|
5364
|
+
function isDayOfWeek(value) {
|
|
5365
|
+
return VALID_DAYS_OF_WEEK.has(value);
|
|
5366
|
+
}
|
|
5367
|
+
|
|
5368
|
+
//#endregion
|
|
5369
|
+
//#region src/core/adapters/kintone/reportConfigurator.ts
|
|
5276
5370
|
function fromKintoneGroup(raw) {
|
|
5277
5371
|
const result = { code: raw.code };
|
|
5278
5372
|
if (raw.per !== void 0) {
|
|
5279
|
-
if (!
|
|
5373
|
+
if (!isGroupPer(raw.per)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected group per value from kintone API: ${raw.per}`);
|
|
5280
5374
|
return {
|
|
5281
5375
|
...result,
|
|
5282
5376
|
per: raw.per
|
|
@@ -5285,7 +5379,7 @@ function fromKintoneGroup(raw) {
|
|
|
5285
5379
|
return result;
|
|
5286
5380
|
}
|
|
5287
5381
|
function fromKintoneAggregation(raw) {
|
|
5288
|
-
if (!
|
|
5382
|
+
if (!isAggregationType(raw.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected aggregation type value from kintone API: ${raw.type}`);
|
|
5289
5383
|
const result = { type: raw.type };
|
|
5290
5384
|
if (raw.code !== void 0) return {
|
|
5291
5385
|
...result,
|
|
@@ -5294,30 +5388,37 @@ function fromKintoneAggregation(raw) {
|
|
|
5294
5388
|
return result;
|
|
5295
5389
|
}
|
|
5296
5390
|
function fromKintoneSort(raw) {
|
|
5297
|
-
if (!
|
|
5298
|
-
if (!
|
|
5391
|
+
if (!isSortBy(raw.by)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected sort by value from kintone API: ${raw.by}`);
|
|
5392
|
+
if (!isSortOrder(raw.order)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected sort order value from kintone API: ${raw.order}`);
|
|
5299
5393
|
return {
|
|
5300
5394
|
by: raw.by,
|
|
5301
5395
|
order: raw.order
|
|
5302
5396
|
};
|
|
5303
5397
|
}
|
|
5304
5398
|
function fromKintonePeriodicReportPeriod(raw) {
|
|
5305
|
-
if (!
|
|
5306
|
-
if (raw.pattern !== void 0 && !
|
|
5399
|
+
if (!isPeriodicReportEvery(raw.every)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected periodicReport every value from kintone API: ${raw.every}`);
|
|
5400
|
+
if (raw.pattern !== void 0 && !isPeriodicReportPattern(raw.pattern)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected periodicReport pattern value from kintone API: ${raw.pattern}`);
|
|
5307
5401
|
let dayOfMonth;
|
|
5308
5402
|
if (raw.dayOfMonth !== void 0) if (String(raw.dayOfMonth) === "END_OF_MONTH") dayOfMonth = "END_OF_MONTH";
|
|
5309
5403
|
else {
|
|
5310
5404
|
const parsed = Number(raw.dayOfMonth);
|
|
5311
|
-
if (Number.
|
|
5405
|
+
if (!Number.isFinite(parsed) || !Number.isInteger(parsed)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected periodicReport dayOfMonth value from kintone API: ${String(raw.dayOfMonth)}`);
|
|
5312
5406
|
dayOfMonth = parsed;
|
|
5313
5407
|
}
|
|
5314
5408
|
return {
|
|
5315
5409
|
every: raw.every,
|
|
5316
|
-
...raw.month !== void 0 ? { month:
|
|
5317
|
-
|
|
5410
|
+
...raw.month !== void 0 ? { month: (() => {
|
|
5411
|
+
const m = Number(raw.month);
|
|
5412
|
+
if (!Number.isFinite(m)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected non-numeric month from kintone API: ${raw.month}`);
|
|
5413
|
+
return m;
|
|
5414
|
+
})() } : {},
|
|
5415
|
+
...raw.pattern !== void 0 && isPeriodicReportPattern(raw.pattern) ? { pattern: raw.pattern } : {},
|
|
5318
5416
|
...dayOfMonth !== void 0 ? { dayOfMonth } : {},
|
|
5319
5417
|
...raw.time !== void 0 ? { time: raw.time } : {},
|
|
5320
|
-
...raw.dayOfWeek !== void 0 ?
|
|
5418
|
+
...raw.dayOfWeek !== void 0 ? (() => {
|
|
5419
|
+
if (!isDayOfWeek(raw.dayOfWeek)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected periodicReport dayOfWeek value from kintone API: ${raw.dayOfWeek}`);
|
|
5420
|
+
return { dayOfWeek: raw.dayOfWeek };
|
|
5421
|
+
})() : {},
|
|
5321
5422
|
...raw.minute !== void 0 ? { minute: raw.minute } : {}
|
|
5322
5423
|
};
|
|
5323
5424
|
}
|
|
@@ -5328,12 +5429,16 @@ function fromKintonePeriodicReport(raw) {
|
|
|
5328
5429
|
};
|
|
5329
5430
|
}
|
|
5330
5431
|
function fromKintoneReportConfig(raw) {
|
|
5331
|
-
if (!
|
|
5332
|
-
if (raw.chartMode !== void 0 && raw.chartMode !== "" && !
|
|
5432
|
+
if (!isChartType(raw.chartType)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected chartType value from kintone API: ${raw.chartType}`);
|
|
5433
|
+
if (raw.chartMode !== void 0 && raw.chartMode !== "" && !isChartMode(raw.chartMode)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected chartMode value from kintone API: ${raw.chartMode}`);
|
|
5333
5434
|
const result = {
|
|
5334
5435
|
chartType: raw.chartType,
|
|
5335
|
-
...raw.chartMode !== void 0 && raw.chartMode !== "" &&
|
|
5336
|
-
index:
|
|
5436
|
+
...raw.chartMode !== void 0 && raw.chartMode !== "" && isChartMode(raw.chartMode) ? { chartMode: raw.chartMode } : {},
|
|
5437
|
+
index: (() => {
|
|
5438
|
+
const idx = Number(raw.index);
|
|
5439
|
+
if (!Number.isFinite(idx)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected non-numeric index from kintone API: ${raw.index}`);
|
|
5440
|
+
return idx;
|
|
5441
|
+
})(),
|
|
5337
5442
|
name: raw.name,
|
|
5338
5443
|
groups: raw.groups.map(fromKintoneGroup),
|
|
5339
5444
|
aggregations: raw.aggregations.map(fromKintoneAggregation),
|
|
@@ -5366,7 +5471,7 @@ function toKintonePeriodicReportPeriod(period) {
|
|
|
5366
5471
|
const result = { every: period.every };
|
|
5367
5472
|
if (period.month !== void 0) result.month = String(period.month);
|
|
5368
5473
|
if (period.pattern !== void 0) result.pattern = period.pattern;
|
|
5369
|
-
if (period.dayOfMonth !== void 0) result.dayOfMonth = period.dayOfMonth;
|
|
5474
|
+
if (period.dayOfMonth !== void 0) result.dayOfMonth = typeof period.dayOfMonth === "number" ? String(period.dayOfMonth) : period.dayOfMonth;
|
|
5370
5475
|
if (period.time !== void 0) result.time = period.time;
|
|
5371
5476
|
if (period.dayOfWeek !== void 0) result.dayOfWeek = period.dayOfWeek;
|
|
5372
5477
|
if (period.minute !== void 0) result.minute = period.minute;
|
|
@@ -5463,16 +5568,31 @@ const VIEW_TYPES = [
|
|
|
5463
5568
|
"CUSTOM"
|
|
5464
5569
|
];
|
|
5465
5570
|
const VALID_VIEW_TYPES = new Set(VIEW_TYPES);
|
|
5571
|
+
function isViewType(value) {
|
|
5572
|
+
return VALID_VIEW_TYPES.has(value);
|
|
5573
|
+
}
|
|
5466
5574
|
const DEVICE_TYPES = ["DESKTOP", "ANY"];
|
|
5467
5575
|
const VALID_DEVICE_TYPES = new Set(DEVICE_TYPES);
|
|
5576
|
+
function isDeviceType(value) {
|
|
5577
|
+
return VALID_DEVICE_TYPES.has(value);
|
|
5578
|
+
}
|
|
5468
5579
|
|
|
5469
5580
|
//#endregion
|
|
5470
5581
|
//#region src/core/adapters/kintone/viewConfigurator.ts
|
|
5471
5582
|
function fromKintoneView(name, raw) {
|
|
5472
|
-
if (!
|
|
5583
|
+
if (!isViewType(raw.type)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected view type from kintone API: ${raw.type}`);
|
|
5584
|
+
let device;
|
|
5585
|
+
if (raw.device !== void 0) {
|
|
5586
|
+
if (!isDeviceType(raw.device)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected device type from kintone API: ${raw.device}`);
|
|
5587
|
+
device = raw.device;
|
|
5588
|
+
}
|
|
5473
5589
|
return {
|
|
5474
5590
|
type: raw.type,
|
|
5475
|
-
index:
|
|
5591
|
+
index: (() => {
|
|
5592
|
+
const idx = typeof raw.index === "string" ? Number(raw.index) : raw.index;
|
|
5593
|
+
if (!Number.isFinite(idx)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected non-numeric index from kintone API: ${raw.index}`);
|
|
5594
|
+
return idx;
|
|
5595
|
+
})(),
|
|
5476
5596
|
name,
|
|
5477
5597
|
...raw.builtinType !== void 0 && { builtinType: raw.builtinType },
|
|
5478
5598
|
...raw.fields !== void 0 && { fields: raw.fields },
|
|
@@ -5480,10 +5600,7 @@ function fromKintoneView(name, raw) {
|
|
|
5480
5600
|
...raw.title !== void 0 && { title: raw.title },
|
|
5481
5601
|
...raw.html !== void 0 && { html: raw.html },
|
|
5482
5602
|
...raw.pager !== void 0 && { pager: raw.pager },
|
|
5483
|
-
...
|
|
5484
|
-
if (!VALID_DEVICE_TYPES.has(raw.device)) throw new SystemError(SystemErrorCode.ExternalApiError, `Unexpected device type from kintone API: ${raw.device}`);
|
|
5485
|
-
return raw.device;
|
|
5486
|
-
})() },
|
|
5603
|
+
...device !== void 0 && { device },
|
|
5487
5604
|
...raw.filterCond !== void 0 && { filterCond: raw.filterCond },
|
|
5488
5605
|
...raw.sort !== void 0 && { sort: raw.sort }
|
|
5489
5606
|
};
|
|
@@ -5915,11 +6032,7 @@ function serializeConfig(config) {
|
|
|
5915
6032
|
return result;
|
|
5916
6033
|
}
|
|
5917
6034
|
const GeneralSettingsConfigSerializer = { serialize: (config) => {
|
|
5918
|
-
return
|
|
5919
|
-
lineWidth: 0,
|
|
5920
|
-
defaultKeyType: "PLAIN",
|
|
5921
|
-
defaultStringType: "PLAIN"
|
|
5922
|
-
});
|
|
6035
|
+
return serializeToYaml(serializeConfig(config));
|
|
5923
6036
|
} };
|
|
5924
6037
|
|
|
5925
6038
|
//#endregion
|
|
@@ -5958,7 +6071,7 @@ function serializeGeneralNotification(notification) {
|
|
|
5958
6071
|
if (notification.includeSubs !== void 0) result.includeSubs = notification.includeSubs;
|
|
5959
6072
|
return result;
|
|
5960
6073
|
}
|
|
5961
|
-
function
|
|
6074
|
+
function serializeTarget(target) {
|
|
5962
6075
|
const result = { entity: serializeEntity$1(target.entity) };
|
|
5963
6076
|
if (target.includeSubs !== void 0) result.includeSubs = target.includeSubs;
|
|
5964
6077
|
return result;
|
|
@@ -5967,21 +6080,16 @@ function serializePerRecordNotification(notification) {
|
|
|
5967
6080
|
return {
|
|
5968
6081
|
filterCond: notification.filterCond,
|
|
5969
6082
|
title: notification.title,
|
|
5970
|
-
targets: notification.targets.map(
|
|
6083
|
+
targets: notification.targets.map(serializeTarget)
|
|
5971
6084
|
};
|
|
5972
6085
|
}
|
|
5973
|
-
function serializeReminderTarget(target) {
|
|
5974
|
-
const result = { entity: serializeEntity$1(target.entity) };
|
|
5975
|
-
if (target.includeSubs !== void 0) result.includeSubs = target.includeSubs;
|
|
5976
|
-
return result;
|
|
5977
|
-
}
|
|
5978
6086
|
function serializeReminderNotification(notification) {
|
|
5979
6087
|
const result = {
|
|
5980
6088
|
code: notification.code,
|
|
5981
6089
|
daysLater: notification.daysLater,
|
|
5982
6090
|
filterCond: notification.filterCond,
|
|
5983
6091
|
title: notification.title,
|
|
5984
|
-
targets: notification.targets.map(
|
|
6092
|
+
targets: notification.targets.map(serializeTarget)
|
|
5985
6093
|
};
|
|
5986
6094
|
if (notification.hoursLater !== void 0) result.hoursLater = notification.hoursLater;
|
|
5987
6095
|
if (notification.time !== void 0) result.time = notification.time;
|
|
@@ -5998,11 +6106,7 @@ const NotificationConfigSerializer = { serialize: (config) => {
|
|
|
5998
6106
|
timezone: config.reminder.timezone,
|
|
5999
6107
|
notifications: config.reminder.notifications.map(serializeReminderNotification)
|
|
6000
6108
|
};
|
|
6001
|
-
return
|
|
6002
|
-
lineWidth: 0,
|
|
6003
|
-
defaultKeyType: "PLAIN",
|
|
6004
|
-
defaultStringType: "PLAIN"
|
|
6005
|
-
});
|
|
6109
|
+
return serializeToYaml(serialized);
|
|
6006
6110
|
} };
|
|
6007
6111
|
|
|
6008
6112
|
//#endregion
|
|
@@ -6037,15 +6141,11 @@ async function saveNotification({ container, input }) {
|
|
|
6037
6141
|
//#endregion
|
|
6038
6142
|
//#region src/core/domain/plugin/services/configSerializer.ts
|
|
6039
6143
|
const PluginConfigSerializer = { serialize: (config) => {
|
|
6040
|
-
return
|
|
6144
|
+
return serializeToYaml({ plugins: config.plugins.map((plugin) => ({
|
|
6041
6145
|
id: plugin.id,
|
|
6042
6146
|
name: plugin.name,
|
|
6043
6147
|
enabled: plugin.enabled
|
|
6044
|
-
})) }
|
|
6045
|
-
lineWidth: 0,
|
|
6046
|
-
defaultKeyType: "PLAIN",
|
|
6047
|
-
defaultStringType: "PLAIN"
|
|
6048
|
-
});
|
|
6148
|
+
})) });
|
|
6049
6149
|
} };
|
|
6050
6150
|
|
|
6051
6151
|
//#endregion
|
|
@@ -6081,7 +6181,7 @@ const ProcessManagementConfigSerializer = { serialize: (config) => {
|
|
|
6081
6181
|
entities: state.assignee.entities.map(serializeProcessEntity)
|
|
6082
6182
|
}
|
|
6083
6183
|
};
|
|
6084
|
-
return
|
|
6184
|
+
return serializeToYaml({
|
|
6085
6185
|
enable: config.enable,
|
|
6086
6186
|
states: serializedStates,
|
|
6087
6187
|
actions: config.actions.map((action) => {
|
|
@@ -6095,10 +6195,6 @@ const ProcessManagementConfigSerializer = { serialize: (config) => {
|
|
|
6095
6195
|
if (action.executableUser !== void 0) serializedAction.executableUser = { entities: action.executableUser.entities.map(serializeProcessEntity) };
|
|
6096
6196
|
return serializedAction;
|
|
6097
6197
|
})
|
|
6098
|
-
}, {
|
|
6099
|
-
lineWidth: 0,
|
|
6100
|
-
defaultKeyType: "PLAIN",
|
|
6101
|
-
defaultStringType: "PLAIN"
|
|
6102
6198
|
});
|
|
6103
6199
|
} };
|
|
6104
6200
|
|
|
@@ -6133,14 +6229,10 @@ function serializeRecordRightEntity(entity) {
|
|
|
6133
6229
|
};
|
|
6134
6230
|
}
|
|
6135
6231
|
const RecordPermissionConfigSerializer = { serialize: (config) => {
|
|
6136
|
-
return
|
|
6232
|
+
return serializeToYaml({ rights: config.rights.map((right) => ({
|
|
6137
6233
|
filterCond: right.filterCond,
|
|
6138
6234
|
entities: right.entities.map(serializeRecordRightEntity)
|
|
6139
|
-
})) }
|
|
6140
|
-
lineWidth: 0,
|
|
6141
|
-
defaultKeyType: "PLAIN",
|
|
6142
|
-
defaultStringType: "PLAIN"
|
|
6143
|
-
});
|
|
6235
|
+
})) });
|
|
6144
6236
|
} };
|
|
6145
6237
|
|
|
6146
6238
|
//#endregion
|
|
@@ -6211,11 +6303,7 @@ const ReportConfigSerializer = { serialize: (config) => {
|
|
|
6211
6303
|
const reports = {};
|
|
6212
6304
|
for (const [name, reportConfig] of Object.entries(config.reports)) reports[name] = serializeReportConfig(reportConfig);
|
|
6213
6305
|
serialized.reports = reports;
|
|
6214
|
-
return
|
|
6215
|
-
lineWidth: 0,
|
|
6216
|
-
defaultKeyType: "PLAIN",
|
|
6217
|
-
defaultStringType: "PLAIN"
|
|
6218
|
-
});
|
|
6306
|
+
return serializeToYaml(serialized);
|
|
6219
6307
|
} };
|
|
6220
6308
|
|
|
6221
6309
|
//#endregion
|
|
@@ -6299,11 +6387,7 @@ function serializeViewConfig(config) {
|
|
|
6299
6387
|
const ViewConfigSerializer = { serialize: (config) => {
|
|
6300
6388
|
const serialized = {};
|
|
6301
6389
|
for (const [name, viewConfig] of Object.entries(config.views)) serialized[name] = serializeViewConfig(viewConfig);
|
|
6302
|
-
return
|
|
6303
|
-
lineWidth: 0,
|
|
6304
|
-
defaultKeyType: "PLAIN",
|
|
6305
|
-
defaultStringType: "PLAIN"
|
|
6306
|
-
});
|
|
6390
|
+
return serializeToYaml({ views: serialized });
|
|
6307
6391
|
} };
|
|
6308
6392
|
|
|
6309
6393
|
//#endregion
|
|
@@ -6660,68 +6744,57 @@ var init_default = define({
|
|
|
6660
6744
|
|
|
6661
6745
|
//#endregion
|
|
6662
6746
|
//#region src/core/domain/notification/services/configParser.ts
|
|
6663
|
-
const VALID_ENTITY_TYPES$2 = new Set([
|
|
6664
|
-
"USER",
|
|
6665
|
-
"GROUP",
|
|
6666
|
-
"ORGANIZATION",
|
|
6667
|
-
"FIELD_ENTITY"
|
|
6668
|
-
]);
|
|
6669
6747
|
function parseEntity$1(raw, context) {
|
|
6670
6748
|
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `${context}: entity must be an object`);
|
|
6671
|
-
|
|
6672
|
-
if (typeof
|
|
6673
|
-
if (typeof obj.code !== "string" || obj.code.length === 0) throw new BusinessRuleError(NotificationErrorCode.NtEmptyEntityCode, `${context}: entity must have a non-empty "code" property`);
|
|
6749
|
+
if (typeof raw.type !== "string" || !isNotificationEntityType(raw.type)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidEntityType, `${context}: entity has invalid type: ${String(raw.type)}. Must be USER, GROUP, ORGANIZATION, or FIELD_ENTITY`);
|
|
6750
|
+
if (typeof raw.code !== "string" || raw.code.length === 0) throw new BusinessRuleError(NotificationErrorCode.NtEmptyEntityCode, `${context}: entity must have a non-empty "code" property`);
|
|
6674
6751
|
return {
|
|
6675
|
-
type:
|
|
6676
|
-
code:
|
|
6752
|
+
type: raw.type,
|
|
6753
|
+
code: raw.code
|
|
6677
6754
|
};
|
|
6678
6755
|
}
|
|
6679
6756
|
function parseGeneralNotification(raw, index) {
|
|
6680
6757
|
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `General notification at index ${index} must be an object`);
|
|
6681
|
-
const obj = raw;
|
|
6682
6758
|
const result = {
|
|
6683
|
-
entity: parseEntity$1(
|
|
6684
|
-
recordAdded: Boolean(
|
|
6685
|
-
recordEdited: Boolean(
|
|
6686
|
-
commentAdded: Boolean(
|
|
6687
|
-
statusChanged: Boolean(
|
|
6688
|
-
fileImported: Boolean(
|
|
6689
|
-
};
|
|
6690
|
-
if (
|
|
6759
|
+
entity: parseEntity$1(raw.entity, `General notification at index ${index}`),
|
|
6760
|
+
recordAdded: Boolean(raw.recordAdded),
|
|
6761
|
+
recordEdited: Boolean(raw.recordEdited),
|
|
6762
|
+
commentAdded: Boolean(raw.commentAdded),
|
|
6763
|
+
statusChanged: Boolean(raw.statusChanged),
|
|
6764
|
+
fileImported: Boolean(raw.fileImported)
|
|
6765
|
+
};
|
|
6766
|
+
if (raw.includeSubs !== void 0 && raw.includeSubs !== null) return {
|
|
6691
6767
|
...result,
|
|
6692
|
-
includeSubs: Boolean(
|
|
6768
|
+
includeSubs: Boolean(raw.includeSubs)
|
|
6693
6769
|
};
|
|
6694
6770
|
return result;
|
|
6695
6771
|
}
|
|
6696
6772
|
function parseGeneralConfig(raw) {
|
|
6697
6773
|
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, "\"general\" must be an object");
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
const notifications = obj.notifications.map((item, i) => parseGeneralNotification(item, i));
|
|
6774
|
+
if (!Array.isArray(raw.notifications)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, "\"general\" must have a \"notifications\" array");
|
|
6775
|
+
const notifications = raw.notifications.map((item, i) => parseGeneralNotification(item, i));
|
|
6701
6776
|
return {
|
|
6702
|
-
notifyToCommenter: Boolean(
|
|
6777
|
+
notifyToCommenter: Boolean(raw.notifyToCommenter),
|
|
6703
6778
|
notifications
|
|
6704
6779
|
};
|
|
6705
6780
|
}
|
|
6706
|
-
function
|
|
6707
|
-
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure,
|
|
6708
|
-
const
|
|
6709
|
-
|
|
6710
|
-
if (obj.includeSubs !== void 0 && obj.includeSubs !== null) return {
|
|
6781
|
+
function parseTarget(raw, index, context) {
|
|
6782
|
+
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `${context} target at index ${index} must be an object`);
|
|
6783
|
+
const result = { entity: parseEntity$1(raw.entity, `${context} target at index ${index}`) };
|
|
6784
|
+
if (raw.includeSubs !== void 0 && raw.includeSubs !== null) return {
|
|
6711
6785
|
...result,
|
|
6712
|
-
includeSubs: Boolean(
|
|
6786
|
+
includeSubs: Boolean(raw.includeSubs)
|
|
6713
6787
|
};
|
|
6714
6788
|
return result;
|
|
6715
6789
|
}
|
|
6716
6790
|
function parsePerRecordNotification(raw, index) {
|
|
6717
6791
|
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Per-record notification at index ${index} must be an object`);
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
if (typeof obj.filterCond !== "string") throw new BusinessRuleError(NotificationErrorCode.NtMissingRequiredField, `Per-record notification at index ${index} must have a "filterCond" string property`);
|
|
6792
|
+
if (!Array.isArray(raw.targets)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Per-record notification at index ${index} must have a "targets" array`);
|
|
6793
|
+
const targets = raw.targets.map((item, i) => parseTarget(item, i, "Per-record"));
|
|
6794
|
+
if (typeof raw.filterCond !== "string") throw new BusinessRuleError(NotificationErrorCode.NtMissingRequiredField, `Per-record notification at index ${index} must have a "filterCond" string property`);
|
|
6722
6795
|
return {
|
|
6723
|
-
filterCond:
|
|
6724
|
-
title: typeof
|
|
6796
|
+
filterCond: raw.filterCond,
|
|
6797
|
+
title: typeof raw.title === "string" ? raw.title : "",
|
|
6725
6798
|
targets
|
|
6726
6799
|
};
|
|
6727
6800
|
}
|
|
@@ -6729,63 +6802,50 @@ function parsePerRecordConfig(raw) {
|
|
|
6729
6802
|
if (!Array.isArray(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, "\"perRecord\" must be an array");
|
|
6730
6803
|
return raw.map((item, i) => parsePerRecordNotification(item, i));
|
|
6731
6804
|
}
|
|
6732
|
-
function parseReminderTarget(raw, index) {
|
|
6733
|
-
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Reminder target at index ${index} must be an object`);
|
|
6734
|
-
const obj = raw;
|
|
6735
|
-
const result = { entity: parseEntity$1(obj.entity, `Reminder target at index ${index}`) };
|
|
6736
|
-
if (obj.includeSubs !== void 0 && obj.includeSubs !== null) return {
|
|
6737
|
-
...result,
|
|
6738
|
-
includeSubs: Boolean(obj.includeSubs)
|
|
6739
|
-
};
|
|
6740
|
-
return result;
|
|
6741
|
-
}
|
|
6742
6805
|
function parseReminderNotification(raw, index) {
|
|
6743
6806
|
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Reminder notification at index ${index} must be an object`);
|
|
6744
|
-
|
|
6745
|
-
if (
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
if (
|
|
6749
|
-
const hasHoursLater =
|
|
6750
|
-
const hasTime =
|
|
6807
|
+
if (typeof raw.code !== "string" || raw.code.length === 0) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Reminder notification at index ${index} must have a non-empty "code" property`);
|
|
6808
|
+
if (!Array.isArray(raw.targets)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Reminder notification at index ${index} must have a "targets" array`);
|
|
6809
|
+
const targets = raw.targets.map((item, i) => parseTarget(item, i, "Reminder"));
|
|
6810
|
+
if (typeof raw.daysLater !== "number") throw new BusinessRuleError(NotificationErrorCode.NtMissingRequiredField, `Reminder notification at index ${index} must have a "daysLater" property`);
|
|
6811
|
+
if (!Number.isInteger(raw.daysLater) || raw.daysLater < 0) throw new BusinessRuleError(NotificationErrorCode.NtInvalidDaysLater, `Reminder notification at index ${index} has invalid "daysLater": ${raw.daysLater}. Must be a non-negative integer`);
|
|
6812
|
+
const hasHoursLater = raw.hoursLater !== void 0 && raw.hoursLater !== null;
|
|
6813
|
+
const hasTime = raw.time !== void 0 && raw.time !== null;
|
|
6751
6814
|
if (hasHoursLater && hasTime) throw new BusinessRuleError(NotificationErrorCode.NtConflictingTimingFields, `Reminder notification at index ${index} must not have both "hoursLater" and "time"`);
|
|
6815
|
+
if (hasHoursLater && (typeof raw.hoursLater !== "number" || !Number.isInteger(raw.hoursLater) || raw.hoursLater < 0)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidHoursLater, `Reminder notification at index ${index} has invalid "hoursLater": ${String(raw.hoursLater)}. Must be a non-negative integer`);
|
|
6816
|
+
if (hasTime && typeof raw.time !== "string") throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, `Reminder notification at index ${index} has non-string "time": ${String(raw.time)}`);
|
|
6752
6817
|
const result = {
|
|
6753
|
-
code:
|
|
6754
|
-
daysLater:
|
|
6755
|
-
filterCond: typeof
|
|
6756
|
-
title: typeof
|
|
6818
|
+
code: raw.code,
|
|
6819
|
+
daysLater: raw.daysLater,
|
|
6820
|
+
filterCond: typeof raw.filterCond === "string" ? raw.filterCond : "",
|
|
6821
|
+
title: typeof raw.title === "string" ? raw.title : "",
|
|
6757
6822
|
targets
|
|
6758
6823
|
};
|
|
6759
|
-
if (hasHoursLater) return {
|
|
6824
|
+
if (hasHoursLater && typeof raw.hoursLater === "number") return {
|
|
6760
6825
|
...result,
|
|
6761
|
-
hoursLater:
|
|
6826
|
+
hoursLater: raw.hoursLater
|
|
6762
6827
|
};
|
|
6763
6828
|
if (hasTime) return {
|
|
6764
6829
|
...result,
|
|
6765
|
-
time: typeof
|
|
6830
|
+
time: typeof raw.time === "string" ? raw.time : ""
|
|
6766
6831
|
};
|
|
6767
6832
|
return result;
|
|
6768
6833
|
}
|
|
6769
6834
|
function parseReminderConfig(raw) {
|
|
6770
6835
|
if (!isRecord(raw)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, "\"reminder\" must be an object");
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
const notifications = obj.notifications.map((item, i) => parseReminderNotification(item, i));
|
|
6836
|
+
if (!Array.isArray(raw.notifications)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, "\"reminder\" must have a \"notifications\" array");
|
|
6837
|
+
const notifications = raw.notifications.map((item, i) => parseReminderNotification(item, i));
|
|
6774
6838
|
return {
|
|
6775
|
-
timezone: typeof
|
|
6839
|
+
timezone: typeof raw.timezone === "string" ? raw.timezone : "Asia/Tokyo",
|
|
6776
6840
|
notifications
|
|
6777
6841
|
};
|
|
6778
6842
|
}
|
|
6779
6843
|
const NotificationConfigParser = { parse: (rawText) => {
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
}
|
|
6785
|
-
throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
6786
|
-
}
|
|
6787
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(NotificationErrorCode.NtInvalidConfigStructure, "Config must be a YAML object");
|
|
6788
|
-
const obj = parsed;
|
|
6844
|
+
const obj = parseYamlConfig(rawText, {
|
|
6845
|
+
emptyConfigText: NotificationErrorCode.NtEmptyConfigText,
|
|
6846
|
+
invalidConfigYaml: NotificationErrorCode.NtInvalidConfigYaml,
|
|
6847
|
+
invalidConfigStructure: NotificationErrorCode.NtInvalidConfigStructure
|
|
6848
|
+
}, "Notification");
|
|
6789
6849
|
const config = {};
|
|
6790
6850
|
if (obj.general !== void 0) config.general = parseGeneralConfig(obj.general);
|
|
6791
6851
|
if (obj.perRecord !== void 0) config.perRecord = parsePerRecordConfig(obj.perRecord);
|
|
@@ -7204,26 +7264,28 @@ var notification_default = define({
|
|
|
7204
7264
|
//#region src/core/domain/plugin/services/configParser.ts
|
|
7205
7265
|
function parsePluginEntry(raw, index) {
|
|
7206
7266
|
if (!isRecord(raw)) throw new BusinessRuleError(PluginErrorCode.PlInvalidConfigStructure, `Plugin at index ${index} must be an object`);
|
|
7207
|
-
|
|
7208
|
-
if (
|
|
7267
|
+
if (typeof raw.id !== "string" || raw.id.length === 0) throw new BusinessRuleError(PluginErrorCode.PlEmptyPluginId, `Plugin at index ${index} must have a non-empty "id" property`);
|
|
7268
|
+
if (raw.enabled !== void 0 && raw.enabled !== null && typeof raw.enabled !== "boolean") throw new BusinessRuleError(PluginErrorCode.PlInvalidConfigStructure, `Plugin at index ${index} has invalid "enabled": must be a boolean`);
|
|
7209
7269
|
return {
|
|
7210
|
-
id:
|
|
7211
|
-
name: typeof
|
|
7212
|
-
enabled: typeof
|
|
7270
|
+
id: raw.id,
|
|
7271
|
+
name: typeof raw.name === "string" ? raw.name : "",
|
|
7272
|
+
enabled: typeof raw.enabled === "boolean" ? raw.enabled : true
|
|
7213
7273
|
};
|
|
7214
7274
|
}
|
|
7215
7275
|
const PluginConfigParser = { parse: (rawText) => {
|
|
7216
|
-
|
|
7217
|
-
|
|
7218
|
-
|
|
7219
|
-
|
|
7220
|
-
}
|
|
7221
|
-
throw new BusinessRuleError(PluginErrorCode.PlInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
7222
|
-
}
|
|
7223
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(PluginErrorCode.PlInvalidConfigStructure, "Config must be a YAML object");
|
|
7224
|
-
const obj = parsed;
|
|
7276
|
+
const obj = parseYamlConfig(rawText, {
|
|
7277
|
+
emptyConfigText: PluginErrorCode.PlEmptyConfigText,
|
|
7278
|
+
invalidConfigYaml: PluginErrorCode.PlInvalidConfigYaml,
|
|
7279
|
+
invalidConfigStructure: PluginErrorCode.PlInvalidConfigStructure
|
|
7280
|
+
}, "Plugin");
|
|
7225
7281
|
if (!Array.isArray(obj.plugins)) throw new BusinessRuleError(PluginErrorCode.PlInvalidConfigStructure, "Config must have a \"plugins\" array");
|
|
7226
|
-
|
|
7282
|
+
const plugins = obj.plugins.map((item, i) => parsePluginEntry(item, i));
|
|
7283
|
+
const seenIds = /* @__PURE__ */ new Set();
|
|
7284
|
+
for (const plugin of plugins) {
|
|
7285
|
+
if (seenIds.has(plugin.id)) throw new BusinessRuleError(PluginErrorCode.PlDuplicatePluginId, `Duplicate plugin ID: "${plugin.id}"`);
|
|
7286
|
+
seenIds.add(plugin.id);
|
|
7287
|
+
}
|
|
7288
|
+
return { plugins };
|
|
7227
7289
|
} };
|
|
7228
7290
|
|
|
7229
7291
|
//#endregion
|
|
@@ -7447,85 +7509,77 @@ const VALID_ENTITY_TYPES$1 = new Set([
|
|
|
7447
7509
|
const VALID_ACTION_TYPES = new Set(["PRIMARY", "SECONDARY"]);
|
|
7448
7510
|
function parseProcessEntity(raw, index) {
|
|
7449
7511
|
if (!isRecord(raw)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Entity at index ${index} must be an object`);
|
|
7450
|
-
const
|
|
7451
|
-
|
|
7452
|
-
const result = { type: obj.type };
|
|
7453
|
-
const withCode = obj.code !== void 0 && obj.code !== null ? {
|
|
7512
|
+
const result = { type: parseEnum(raw.type, VALID_ENTITY_TYPES$1, ProcessManagementErrorCode.PmInvalidEntityType, `Entity at index ${index} has invalid type: ${String(raw.type)}. Must be USER, GROUP, ORGANIZATION, FIELD_ENTITY, CREATOR, or CUSTOM_FIELD`) };
|
|
7513
|
+
const withCode = raw.code !== void 0 && raw.code !== null ? {
|
|
7454
7514
|
...result,
|
|
7455
|
-
code: String(
|
|
7515
|
+
code: String(raw.code)
|
|
7456
7516
|
} : result;
|
|
7457
|
-
if (
|
|
7517
|
+
if (raw.includeSubs !== void 0 && raw.includeSubs !== null) return {
|
|
7458
7518
|
...withCode,
|
|
7459
|
-
includeSubs:
|
|
7519
|
+
includeSubs: parseStrictBoolean(raw.includeSubs, "includeSubs", `Entity at index ${index}`, ProcessManagementErrorCode.PmInvalidBooleanField)
|
|
7460
7520
|
};
|
|
7461
7521
|
return withCode;
|
|
7462
7522
|
}
|
|
7463
7523
|
function parseAssignee(raw, stateName) {
|
|
7464
7524
|
if (!isRecord(raw)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Assignee for state "${stateName}" must be an object`);
|
|
7465
|
-
|
|
7466
|
-
if (typeof obj.type !== "string" || !VALID_ASSIGNEE_TYPES.has(obj.type)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidAssigneeType, `Assignee for state "${stateName}" has invalid type: ${String(obj.type)}. Must be ONE, ALL, or ANY`);
|
|
7467
|
-
if (!Array.isArray(obj.entities)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Assignee for state "${stateName}" must have an "entities" array`);
|
|
7468
|
-
const entities = obj.entities.map((item, i) => parseProcessEntity(item, i));
|
|
7525
|
+
if (!Array.isArray(raw.entities)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Assignee for state "${stateName}" must have an "entities" array`);
|
|
7469
7526
|
return {
|
|
7470
|
-
type:
|
|
7471
|
-
entities
|
|
7527
|
+
type: parseEnum(raw.type, VALID_ASSIGNEE_TYPES, ProcessManagementErrorCode.PmInvalidAssigneeType, `Assignee for state "${stateName}" has invalid type: ${String(raw.type)}. Must be ONE, ALL, or ANY`),
|
|
7528
|
+
entities: raw.entities.map((item, i) => parseProcessEntity(item, i))
|
|
7472
7529
|
};
|
|
7473
7530
|
}
|
|
7474
7531
|
function parseState(raw, stateName) {
|
|
7475
7532
|
if (!isRecord(raw)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `State "${stateName}" must be an object`);
|
|
7476
|
-
|
|
7477
|
-
if (
|
|
7478
|
-
|
|
7479
|
-
const assignee = parseAssignee(obj.assignee, stateName);
|
|
7533
|
+
if (typeof raw.index !== "number") throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `State "${stateName}" must have a numeric "index" property`);
|
|
7534
|
+
if (raw.assignee === void 0 || raw.assignee === null) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `State "${stateName}" must have an "assignee" property`);
|
|
7535
|
+
const assignee = parseAssignee(raw.assignee, stateName);
|
|
7480
7536
|
return {
|
|
7481
|
-
index:
|
|
7537
|
+
index: raw.index,
|
|
7482
7538
|
assignee
|
|
7483
7539
|
};
|
|
7484
7540
|
}
|
|
7485
7541
|
function parseExecutableUser(raw, actionIndex) {
|
|
7486
7542
|
if (!isRecord(raw)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${actionIndex}: executableUser must be an object`);
|
|
7487
|
-
|
|
7488
|
-
|
|
7489
|
-
return { entities: obj.entities.map((item, i) => parseProcessEntity(item, i)) };
|
|
7543
|
+
if (!Array.isArray(raw.entities)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${actionIndex}: executableUser must have an "entities" array`);
|
|
7544
|
+
return { entities: raw.entities.map((item, i) => parseProcessEntity(item, i)) };
|
|
7490
7545
|
}
|
|
7491
7546
|
function parseAction(raw, index) {
|
|
7492
7547
|
if (!isRecord(raw)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${index} must be an object`);
|
|
7493
|
-
|
|
7494
|
-
if (typeof
|
|
7495
|
-
if (typeof
|
|
7496
|
-
|
|
7497
|
-
if (obj.type !== void 0 && obj.type !== null && (typeof obj.type !== "string" || !VALID_ACTION_TYPES.has(obj.type))) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${index} has invalid type: ${String(obj.type)}. Must be PRIMARY or SECONDARY`);
|
|
7498
|
-
const actionType = typeof obj.type === "string" && VALID_ACTION_TYPES.has(obj.type) ? obj.type : "PRIMARY";
|
|
7548
|
+
if (typeof raw.name !== "string") throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${index} must have a "name" string property`);
|
|
7549
|
+
if (typeof raw.from !== "string") throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${index} must have a "from" string property`);
|
|
7550
|
+
if (typeof raw.to !== "string") throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${index} must have a "to" string property`);
|
|
7551
|
+
const actionType = raw.type === void 0 || raw.type === null ? "PRIMARY" : parseEnum(raw.type, VALID_ACTION_TYPES, ProcessManagementErrorCode.PmInvalidConfigStructure, `Action at index ${index} has invalid type: ${String(raw.type)}. Must be PRIMARY or SECONDARY`);
|
|
7499
7552
|
const result = {
|
|
7500
|
-
name:
|
|
7501
|
-
from:
|
|
7502
|
-
to:
|
|
7503
|
-
filterCond: typeof
|
|
7553
|
+
name: raw.name,
|
|
7554
|
+
from: raw.from,
|
|
7555
|
+
to: raw.to,
|
|
7556
|
+
filterCond: typeof raw.filterCond === "string" ? raw.filterCond : "",
|
|
7504
7557
|
type: actionType
|
|
7505
7558
|
};
|
|
7506
|
-
if (actionType === "SECONDARY" &&
|
|
7559
|
+
if (actionType === "SECONDARY" && raw.executableUser !== void 0 && raw.executableUser !== null) return {
|
|
7507
7560
|
...result,
|
|
7508
|
-
executableUser: parseExecutableUser(
|
|
7561
|
+
executableUser: parseExecutableUser(raw.executableUser, index)
|
|
7509
7562
|
};
|
|
7510
7563
|
return result;
|
|
7511
7564
|
}
|
|
7512
7565
|
const ProcessManagementConfigParser = { parse: (rawText) => {
|
|
7513
|
-
|
|
7514
|
-
|
|
7515
|
-
|
|
7516
|
-
|
|
7517
|
-
}
|
|
7518
|
-
|
|
7519
|
-
|
|
7520
|
-
|
|
7521
|
-
const obj = parsed;
|
|
7522
|
-
const enable = obj.enable !== void 0 && obj.enable !== null ? Boolean(obj.enable) : false;
|
|
7523
|
-
if (obj.states !== void 0 && obj.states !== null && !isRecord(obj.states)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, "Config \"states\" must be an object (map of state name to state definition)");
|
|
7524
|
-
const rawStates = isRecord(obj.states) ? obj.states : {};
|
|
7566
|
+
const parsed = parseYamlConfig(rawText, {
|
|
7567
|
+
emptyConfigText: ProcessManagementErrorCode.PmEmptyConfigText,
|
|
7568
|
+
invalidConfigYaml: ProcessManagementErrorCode.PmInvalidConfigYaml,
|
|
7569
|
+
invalidConfigStructure: ProcessManagementErrorCode.PmInvalidConfigStructure
|
|
7570
|
+
}, "Process management");
|
|
7571
|
+
const enable = parsed.enable !== void 0 && parsed.enable !== null ? parseStrictBoolean(parsed.enable, "enable", "Config", ProcessManagementErrorCode.PmInvalidBooleanField) : false;
|
|
7572
|
+
if (parsed.states !== void 0 && parsed.states !== null && !isRecord(parsed.states)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, "Config \"states\" must be an object (map of state name to state definition)");
|
|
7573
|
+
const rawStates = isRecord(parsed.states) ? parsed.states : {};
|
|
7525
7574
|
const states = {};
|
|
7526
7575
|
for (const [name, value] of Object.entries(rawStates)) states[name] = parseState(value, name);
|
|
7527
|
-
if (!Array.isArray(
|
|
7528
|
-
const actions = (
|
|
7576
|
+
if (!Array.isArray(parsed.actions) && parsed.actions !== void 0) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidConfigStructure, "Config \"actions\" must be an array");
|
|
7577
|
+
const actions = (Array.isArray(parsed.actions) ? parsed.actions : []).map((item, i) => parseAction(item, i));
|
|
7578
|
+
const actionNames = /* @__PURE__ */ new Set();
|
|
7579
|
+
for (const action of actions) {
|
|
7580
|
+
if (actionNames.has(action.name)) throw new BusinessRuleError(ProcessManagementErrorCode.PmDuplicateActionName, `Duplicate action name: "${action.name}"`);
|
|
7581
|
+
actionNames.add(action.name);
|
|
7582
|
+
}
|
|
7529
7583
|
const stateNames = new Set(Object.keys(states));
|
|
7530
7584
|
for (const action of actions) {
|
|
7531
7585
|
if (!stateNames.has(action.from)) throw new BusinessRuleError(ProcessManagementErrorCode.PmInvalidActionReference, `Action "${action.name}" references unknown "from" state: "${action.from}"`);
|
|
@@ -7678,7 +7732,7 @@ var capture_default$6 = define({
|
|
|
7678
7732
|
//#region src/core/domain/processManagement/services/diffDetector.ts
|
|
7679
7733
|
function isEntityEqual(a, b) {
|
|
7680
7734
|
if (a.type !== b.type) return false;
|
|
7681
|
-
if (a.code !== b.code) return false;
|
|
7735
|
+
if ((a.code ?? "") !== (b.code ?? "")) return false;
|
|
7682
7736
|
if (Boolean(a.includeSubs) !== Boolean(b.includeSubs)) return false;
|
|
7683
7737
|
return true;
|
|
7684
7738
|
}
|
|
@@ -7816,56 +7870,51 @@ const VALID_ENTITY_TYPES = new Set([
|
|
|
7816
7870
|
"ORGANIZATION",
|
|
7817
7871
|
"FIELD_ENTITY"
|
|
7818
7872
|
]);
|
|
7819
|
-
function parseBooleanField(value, fieldName, context) {
|
|
7820
|
-
if (value === void 0) return false;
|
|
7821
|
-
if (typeof value === "boolean") return value;
|
|
7822
|
-
throw new BusinessRuleError(RecordPermissionErrorCode.RpInvalidPermissionValue, `${context} has invalid "${fieldName}" value: ${String(value)}. Must be a boolean`);
|
|
7823
|
-
}
|
|
7824
7873
|
function parseEntity(raw, index) {
|
|
7825
|
-
|
|
7826
|
-
|
|
7827
|
-
|
|
7828
|
-
|
|
7829
|
-
|
|
7830
|
-
type: obj.type,
|
|
7831
|
-
code: obj.code
|
|
7832
|
-
};
|
|
7874
|
+
return parseEntityBase(raw, index, VALID_ENTITY_TYPES, {
|
|
7875
|
+
invalidStructure: RecordPermissionErrorCode.RpInvalidConfigStructure,
|
|
7876
|
+
invalidType: RecordPermissionErrorCode.RpInvalidEntityType,
|
|
7877
|
+
emptyCode: RecordPermissionErrorCode.RpEmptyEntityCode
|
|
7878
|
+
});
|
|
7833
7879
|
}
|
|
7834
7880
|
function parseRecordRightEntity(raw, index) {
|
|
7835
7881
|
if (!isRecord(raw)) throw new BusinessRuleError(RecordPermissionErrorCode.RpInvalidConfigStructure, `Record right entity at index ${index} must be an object`);
|
|
7836
|
-
const
|
|
7837
|
-
const entity = parseEntity(obj.entity, index);
|
|
7882
|
+
const entity = parseEntity(raw.entity, index);
|
|
7838
7883
|
const context = `Record right entity at index ${index}`;
|
|
7839
7884
|
return {
|
|
7840
7885
|
entity,
|
|
7841
|
-
viewable:
|
|
7842
|
-
editable:
|
|
7843
|
-
deletable:
|
|
7844
|
-
includeSubs:
|
|
7886
|
+
viewable: parseStrictBoolean(raw.viewable, "viewable", context, RecordPermissionErrorCode.RpInvalidPermissionValue, false),
|
|
7887
|
+
editable: parseStrictBoolean(raw.editable, "editable", context, RecordPermissionErrorCode.RpInvalidPermissionValue, false),
|
|
7888
|
+
deletable: parseStrictBoolean(raw.deletable, "deletable", context, RecordPermissionErrorCode.RpInvalidPermissionValue, false),
|
|
7889
|
+
includeSubs: parseStrictBoolean(raw.includeSubs, "includeSubs", context, RecordPermissionErrorCode.RpInvalidPermissionValue, false)
|
|
7845
7890
|
};
|
|
7846
7891
|
}
|
|
7847
7892
|
function parseRecordRight(raw, index) {
|
|
7848
7893
|
if (!isRecord(raw)) throw new BusinessRuleError(RecordPermissionErrorCode.RpInvalidConfigStructure, `Record right at index ${index} must be an object`);
|
|
7849
|
-
|
|
7850
|
-
|
|
7851
|
-
const entities = obj.entities.map((item, i) => parseRecordRightEntity(item, i));
|
|
7894
|
+
if (!Array.isArray(raw.entities)) throw new BusinessRuleError(RecordPermissionErrorCode.RpInvalidConfigStructure, `Record right at index ${index} must have an "entities" array`);
|
|
7895
|
+
const entities = raw.entities.map((item, i) => parseRecordRightEntity(item, i));
|
|
7852
7896
|
return {
|
|
7853
|
-
filterCond: typeof
|
|
7897
|
+
filterCond: typeof raw.filterCond === "string" ? raw.filterCond : "",
|
|
7854
7898
|
entities
|
|
7855
7899
|
};
|
|
7856
7900
|
}
|
|
7857
7901
|
const RecordPermissionConfigParser = { parse: (rawText) => {
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
|
|
7861
|
-
|
|
7862
|
-
}
|
|
7863
|
-
|
|
7902
|
+
const parsed = parseYamlConfig(rawText, {
|
|
7903
|
+
emptyConfigText: RecordPermissionErrorCode.RpEmptyConfigText,
|
|
7904
|
+
invalidConfigYaml: RecordPermissionErrorCode.RpInvalidConfigYaml,
|
|
7905
|
+
invalidConfigStructure: RecordPermissionErrorCode.RpInvalidConfigStructure
|
|
7906
|
+
}, "Record permission");
|
|
7907
|
+
if (!Array.isArray(parsed.rights)) throw new BusinessRuleError(RecordPermissionErrorCode.RpInvalidConfigStructure, "Config must have a \"rights\" array");
|
|
7908
|
+
const rights = parsed.rights.map((item, i) => parseRecordRight(item, i));
|
|
7909
|
+
for (const right of rights) {
|
|
7910
|
+
const seenKeys = /* @__PURE__ */ new Set();
|
|
7911
|
+
for (const re of right.entities) {
|
|
7912
|
+
const key = `${re.entity.type}:${re.entity.code}`;
|
|
7913
|
+
if (seenKeys.has(key)) throw new BusinessRuleError(RecordPermissionErrorCode.RpDuplicateEntity, `Duplicate entity in filterCond "${right.filterCond}": ${re.entity.type} ${re.entity.code}`);
|
|
7914
|
+
seenKeys.add(key);
|
|
7915
|
+
}
|
|
7864
7916
|
}
|
|
7865
|
-
|
|
7866
|
-
const obj = parsed;
|
|
7867
|
-
if (!Array.isArray(obj.rights)) throw new BusinessRuleError(RecordPermissionErrorCode.RpInvalidConfigStructure, "Config must have a \"rights\" array");
|
|
7868
|
-
return { rights: obj.rights.map((item, i) => parseRecordRight(item, i)) };
|
|
7917
|
+
return { rights };
|
|
7869
7918
|
} };
|
|
7870
7919
|
|
|
7871
7920
|
//#endregion
|
|
@@ -8000,7 +8049,7 @@ var capture_default$5 = define({
|
|
|
8000
8049
|
|
|
8001
8050
|
//#endregion
|
|
8002
8051
|
//#region src/core/domain/recordPermission/services/diffDetector.ts
|
|
8003
|
-
function
|
|
8052
|
+
function isRightEqual(a, b) {
|
|
8004
8053
|
return deepEqual(a.entities.map((e) => ({
|
|
8005
8054
|
type: e.entity.type,
|
|
8006
8055
|
code: e.entity.code,
|
|
@@ -8049,7 +8098,7 @@ const RecordPermissionDiffDetector = { detect: (local, remote) => {
|
|
|
8049
8098
|
details: describeRight(remoteRight)
|
|
8050
8099
|
});
|
|
8051
8100
|
else if (localRight && remoteRight) {
|
|
8052
|
-
if (!
|
|
8101
|
+
if (!isRightEqual(localRight, remoteRight)) {
|
|
8053
8102
|
const diffs = [];
|
|
8054
8103
|
if (localRight.entities.length !== remoteRight.entities.length) diffs.push(`entities: ${remoteRight.entities.length} -> ${localRight.entities.length}`);
|
|
8055
8104
|
else diffs.push("entities changed");
|
|
@@ -8111,140 +8160,76 @@ var record_acl_default = define({
|
|
|
8111
8160
|
|
|
8112
8161
|
//#endregion
|
|
8113
8162
|
//#region src/core/domain/report/services/configParser.ts
|
|
8114
|
-
const VALID_CHART_TYPES = new Set([
|
|
8115
|
-
"BAR",
|
|
8116
|
-
"COLUMN",
|
|
8117
|
-
"PIE",
|
|
8118
|
-
"LINE",
|
|
8119
|
-
"PIVOT_TABLE",
|
|
8120
|
-
"TABLE",
|
|
8121
|
-
"AREA",
|
|
8122
|
-
"SPLINE",
|
|
8123
|
-
"SPLINE_AREA"
|
|
8124
|
-
]);
|
|
8125
|
-
const VALID_CHART_MODES = new Set([
|
|
8126
|
-
"NORMAL",
|
|
8127
|
-
"STACKED",
|
|
8128
|
-
"PERCENTAGE"
|
|
8129
|
-
]);
|
|
8130
|
-
const VALID_GROUP_PER = new Set([
|
|
8131
|
-
"YEAR",
|
|
8132
|
-
"QUARTER",
|
|
8133
|
-
"MONTH",
|
|
8134
|
-
"WEEK",
|
|
8135
|
-
"DAY",
|
|
8136
|
-
"HOUR",
|
|
8137
|
-
"MINUTE"
|
|
8138
|
-
]);
|
|
8139
|
-
const VALID_AGGREGATION_TYPES = new Set([
|
|
8140
|
-
"COUNT",
|
|
8141
|
-
"SUM",
|
|
8142
|
-
"AVERAGE",
|
|
8143
|
-
"MAX",
|
|
8144
|
-
"MIN"
|
|
8145
|
-
]);
|
|
8146
|
-
const VALID_SORT_BY = new Set([
|
|
8147
|
-
"TOTAL",
|
|
8148
|
-
"GROUP1",
|
|
8149
|
-
"GROUP2",
|
|
8150
|
-
"GROUP3"
|
|
8151
|
-
]);
|
|
8152
|
-
const VALID_DAY_OF_WEEK = new Set([
|
|
8153
|
-
"SUNDAY",
|
|
8154
|
-
"MONDAY",
|
|
8155
|
-
"TUESDAY",
|
|
8156
|
-
"WEDNESDAY",
|
|
8157
|
-
"THURSDAY",
|
|
8158
|
-
"FRIDAY",
|
|
8159
|
-
"SATURDAY"
|
|
8160
|
-
]);
|
|
8161
|
-
const VALID_PERIODIC_PATTERN = new Set([
|
|
8162
|
-
"JAN_APR_JUL_OCT",
|
|
8163
|
-
"FEB_MAY_AUG_NOV",
|
|
8164
|
-
"MAR_JUN_SEP_DEC"
|
|
8165
|
-
]);
|
|
8166
|
-
const VALID_SORT_ORDER = new Set(["ASC", "DESC"]);
|
|
8167
|
-
const VALID_PERIODIC_EVERY = new Set([
|
|
8168
|
-
"YEAR",
|
|
8169
|
-
"QUARTER",
|
|
8170
|
-
"MONTH",
|
|
8171
|
-
"WEEK",
|
|
8172
|
-
"DAY",
|
|
8173
|
-
"HOUR"
|
|
8174
|
-
]);
|
|
8175
8163
|
function parseGroup(raw, index) {
|
|
8176
8164
|
if (!isRecord(raw)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Group at index ${index} must be an object`);
|
|
8177
|
-
|
|
8178
|
-
|
|
8179
|
-
|
|
8180
|
-
|
|
8181
|
-
if (typeof obj.per !== "string" || !VALID_GROUP_PER.has(obj.per)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Group at index ${index} has invalid per: ${String(obj.per)}. Must be YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, or MINUTE`);
|
|
8165
|
+
if (typeof raw.code !== "string" || raw.code.length === 0) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Group at index ${index} must have a non-empty "code" property`);
|
|
8166
|
+
const result = { code: raw.code };
|
|
8167
|
+
if (raw.per !== void 0 && raw.per !== null) {
|
|
8168
|
+
if (typeof raw.per !== "string" || !isGroupPer(raw.per)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Group at index ${index} has invalid per: ${String(raw.per)}. Must be YEAR, QUARTER, MONTH, WEEK, DAY, HOUR, or MINUTE`);
|
|
8182
8169
|
return {
|
|
8183
8170
|
...result,
|
|
8184
|
-
per:
|
|
8171
|
+
per: raw.per
|
|
8185
8172
|
};
|
|
8186
8173
|
}
|
|
8187
8174
|
return result;
|
|
8188
8175
|
}
|
|
8189
8176
|
function parseAggregation(raw, index) {
|
|
8190
8177
|
if (!isRecord(raw)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Aggregation at index ${index} must be an object`);
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
if (typeof obj.code !== "string") throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Aggregation at index ${index} has invalid code: must be a string`);
|
|
8178
|
+
if (typeof raw.type !== "string" || !isAggregationType(raw.type)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Aggregation at index ${index} has invalid type: ${String(raw.type)}. Must be COUNT, SUM, AVERAGE, MAX, or MIN`);
|
|
8179
|
+
const result = { type: raw.type };
|
|
8180
|
+
if (raw.code !== void 0 && raw.code !== null) {
|
|
8181
|
+
if (typeof raw.code !== "string") throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Aggregation at index ${index} has invalid code: must be a string`);
|
|
8196
8182
|
return {
|
|
8197
8183
|
...result,
|
|
8198
|
-
code:
|
|
8184
|
+
code: raw.code
|
|
8199
8185
|
};
|
|
8200
8186
|
}
|
|
8201
8187
|
return result;
|
|
8202
8188
|
}
|
|
8203
8189
|
function parseSort(raw, index) {
|
|
8204
8190
|
if (!isRecord(raw)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Sort at index ${index} must be an object`);
|
|
8205
|
-
|
|
8206
|
-
if (typeof
|
|
8207
|
-
if (typeof obj.order !== "string" || !VALID_SORT_ORDER.has(obj.order)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Sort at index ${index} has invalid order: ${String(obj.order)}. Must be ASC or DESC`);
|
|
8191
|
+
if (typeof raw.by !== "string" || !isSortBy(raw.by)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Sort at index ${index} has invalid by: ${String(raw.by)}. Must be TOTAL, GROUP1, GROUP2, or GROUP3`);
|
|
8192
|
+
if (typeof raw.order !== "string" || !isSortOrder(raw.order)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Sort at index ${index} has invalid order: ${String(raw.order)}. Must be ASC or DESC`);
|
|
8208
8193
|
return {
|
|
8209
|
-
by:
|
|
8210
|
-
order:
|
|
8194
|
+
by: raw.by,
|
|
8195
|
+
order: raw.order
|
|
8211
8196
|
};
|
|
8212
8197
|
}
|
|
8213
8198
|
function parsePeriodicReportPeriod(raw) {
|
|
8214
8199
|
if (!isRecord(raw)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, "periodicReport.period must be an object");
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
const every = obj.every;
|
|
8200
|
+
if (typeof raw.every !== "string" || !isPeriodicReportEvery(raw.every)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has invalid every: ${String(raw.every)}. Must be YEAR, QUARTER, MONTH, WEEK, DAY, or HOUR`);
|
|
8201
|
+
const every = raw.every;
|
|
8218
8202
|
let month;
|
|
8219
|
-
if (
|
|
8220
|
-
const parsed = Number(
|
|
8221
|
-
if (Number.
|
|
8203
|
+
if (raw.month !== void 0 && raw.month !== null) {
|
|
8204
|
+
const parsed = Number(raw.month);
|
|
8205
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 12) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has invalid month: ${String(raw.month)}. Must be an integer between 1 and 12`);
|
|
8222
8206
|
month = parsed;
|
|
8223
8207
|
}
|
|
8224
8208
|
let pattern;
|
|
8225
|
-
if (
|
|
8226
|
-
if (typeof
|
|
8227
|
-
pattern =
|
|
8209
|
+
if (raw.pattern !== void 0 && raw.pattern !== null) {
|
|
8210
|
+
if (typeof raw.pattern !== "string" || !isPeriodicReportPattern(raw.pattern)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has invalid pattern: ${String(raw.pattern)}. Must be JAN_APR_JUL_OCT, FEB_MAY_AUG_NOV, or MAR_JUN_SEP_DEC`);
|
|
8211
|
+
pattern = raw.pattern;
|
|
8228
8212
|
}
|
|
8229
8213
|
let dayOfMonth;
|
|
8230
|
-
if (
|
|
8214
|
+
if (raw.dayOfMonth !== void 0 && raw.dayOfMonth !== null) if (raw.dayOfMonth === "END_OF_MONTH") dayOfMonth = "END_OF_MONTH";
|
|
8231
8215
|
else {
|
|
8232
|
-
const parsed = Number(
|
|
8233
|
-
if (Number.
|
|
8216
|
+
const parsed = Number(raw.dayOfMonth);
|
|
8217
|
+
if (!Number.isInteger(parsed)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has invalid dayOfMonth: ${String(raw.dayOfMonth)}. Must be an integer or "END_OF_MONTH"`);
|
|
8218
|
+
if (parsed < 1 || parsed > 31) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has out-of-range dayOfMonth: ${parsed}. Must be 1-31`);
|
|
8234
8219
|
dayOfMonth = parsed;
|
|
8235
8220
|
}
|
|
8236
8221
|
let time;
|
|
8237
|
-
if (
|
|
8222
|
+
if (raw.time !== void 0 && raw.time !== null) time = String(raw.time);
|
|
8238
8223
|
let dayOfWeek;
|
|
8239
|
-
if (
|
|
8240
|
-
const dayStr = String(
|
|
8241
|
-
if (!
|
|
8224
|
+
if (raw.dayOfWeek !== void 0 && raw.dayOfWeek !== null) {
|
|
8225
|
+
const dayStr = String(raw.dayOfWeek);
|
|
8226
|
+
if (!isDayOfWeek(dayStr)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has invalid dayOfWeek: ${dayStr}. Must be SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, or SATURDAY`);
|
|
8242
8227
|
dayOfWeek = dayStr;
|
|
8243
8228
|
}
|
|
8244
8229
|
let minute;
|
|
8245
|
-
if (
|
|
8246
|
-
const parsed = Number(
|
|
8247
|
-
if (Number.
|
|
8230
|
+
if (raw.minute !== void 0 && raw.minute !== null) {
|
|
8231
|
+
const parsed = Number(raw.minute);
|
|
8232
|
+
if (!Number.isInteger(parsed) || parsed < 0 || parsed > 50 || parsed % 10 !== 0) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `periodicReport.period has invalid minute: ${String(raw.minute)}. Must be a multiple of 10 (0, 10, 20, 30, 40, 50)`);
|
|
8248
8233
|
minute = parsed;
|
|
8249
8234
|
}
|
|
8250
8235
|
return {
|
|
@@ -8259,32 +8244,34 @@ function parsePeriodicReportPeriod(raw) {
|
|
|
8259
8244
|
}
|
|
8260
8245
|
function parsePeriodicReport(raw) {
|
|
8261
8246
|
if (!isRecord(raw)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, "periodicReport must be an object");
|
|
8262
|
-
const
|
|
8263
|
-
if (typeof
|
|
8264
|
-
const period = parsePeriodicReportPeriod(obj.period);
|
|
8247
|
+
const active = raw.active;
|
|
8248
|
+
if (typeof active !== "boolean") throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, "periodicReport.active must be a boolean");
|
|
8265
8249
|
return {
|
|
8266
|
-
active
|
|
8267
|
-
period
|
|
8250
|
+
active,
|
|
8251
|
+
period: parsePeriodicReportPeriod(raw.period)
|
|
8268
8252
|
};
|
|
8269
8253
|
}
|
|
8270
8254
|
function parseReportConfig(raw, reportName) {
|
|
8255
|
+
if (reportName.length === 0) throw new BusinessRuleError(ReportErrorCode.RtEmptyReportName, "Report name (key) must not be empty");
|
|
8271
8256
|
if (!isRecord(raw)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Report "${reportName}" must be an object`);
|
|
8272
|
-
|
|
8273
|
-
if (typeof obj.chartType !== "string" || !VALID_CHART_TYPES.has(obj.chartType)) throw new BusinessRuleError(ReportErrorCode.RtInvalidChartType, `Report "${reportName}" has invalid chartType: ${String(obj.chartType)}. Must be BAR, COLUMN, PIE, LINE, PIVOT_TABLE, TABLE, AREA, SPLINE, or SPLINE_AREA`);
|
|
8257
|
+
if (typeof raw.chartType !== "string" || !isChartType(raw.chartType)) throw new BusinessRuleError(ReportErrorCode.RtInvalidChartType, `Report "${reportName}" has invalid chartType: ${String(raw.chartType)}. Must be BAR, COLUMN, PIE, LINE, PIVOT_TABLE, TABLE, AREA, SPLINE, or SPLINE_AREA`);
|
|
8274
8258
|
let chartMode;
|
|
8275
|
-
if (
|
|
8276
|
-
if (typeof
|
|
8277
|
-
chartMode =
|
|
8278
|
-
}
|
|
8279
|
-
const name = typeof
|
|
8280
|
-
if (
|
|
8281
|
-
const index =
|
|
8282
|
-
|
|
8283
|
-
const
|
|
8284
|
-
|
|
8285
|
-
const
|
|
8259
|
+
if (raw.chartMode !== void 0 && raw.chartMode !== null) {
|
|
8260
|
+
if (typeof raw.chartMode !== "string" || !isChartMode(raw.chartMode)) throw new BusinessRuleError(ReportErrorCode.RtInvalidChartMode, `Report "${reportName}" has invalid chartMode: ${String(raw.chartMode)}. Must be NORMAL, STACKED, or PERCENTAGE`);
|
|
8261
|
+
chartMode = raw.chartMode;
|
|
8262
|
+
}
|
|
8263
|
+
const name = typeof raw.name === "string" && raw.name.length > 0 ? raw.name : reportName;
|
|
8264
|
+
if (raw.index !== void 0 && raw.index !== null && (typeof raw.index !== "number" || !Number.isInteger(raw.index) || raw.index < 0)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Report "${reportName}" has invalid index: ${String(raw.index)}. Must be a non-negative integer`);
|
|
8265
|
+
const index = typeof raw.index === "number" ? raw.index : 0;
|
|
8266
|
+
if (raw.groups !== void 0 && !Array.isArray(raw.groups)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Report "${reportName}" has invalid groups: must be an array`);
|
|
8267
|
+
const groups = Array.isArray(raw.groups) ? raw.groups.map((item, i) => parseGroup(item, i)) : [];
|
|
8268
|
+
if (raw.aggregations !== void 0 && !Array.isArray(raw.aggregations)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Report "${reportName}" has invalid aggregations: must be an array`);
|
|
8269
|
+
const aggregations = Array.isArray(raw.aggregations) ? raw.aggregations.map((item, i) => parseAggregation(item, i)) : [];
|
|
8270
|
+
const filterCond = typeof raw.filterCond === "string" ? raw.filterCond : "";
|
|
8271
|
+
if (raw.sorts !== void 0 && !Array.isArray(raw.sorts)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, `Report "${reportName}" has invalid sorts: must be an array`);
|
|
8272
|
+
const sorts = Array.isArray(raw.sorts) ? raw.sorts.map((item, i) => parseSort(item, i)) : [];
|
|
8286
8273
|
const result = {
|
|
8287
|
-
chartType:
|
|
8274
|
+
chartType: raw.chartType,
|
|
8288
8275
|
...chartMode !== void 0 ? { chartMode } : {},
|
|
8289
8276
|
index,
|
|
8290
8277
|
name,
|
|
@@ -8293,22 +8280,18 @@ function parseReportConfig(raw, reportName) {
|
|
|
8293
8280
|
filterCond,
|
|
8294
8281
|
sorts
|
|
8295
8282
|
};
|
|
8296
|
-
if (
|
|
8283
|
+
if (raw.periodicReport !== void 0 && raw.periodicReport !== null) return {
|
|
8297
8284
|
...result,
|
|
8298
|
-
periodicReport: parsePeriodicReport(
|
|
8285
|
+
periodicReport: parsePeriodicReport(raw.periodicReport)
|
|
8299
8286
|
};
|
|
8300
8287
|
return result;
|
|
8301
8288
|
}
|
|
8302
8289
|
const ReportConfigParser = { parse: (rawText) => {
|
|
8303
|
-
|
|
8304
|
-
|
|
8305
|
-
|
|
8306
|
-
|
|
8307
|
-
}
|
|
8308
|
-
throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
8309
|
-
}
|
|
8310
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, "Config must be a YAML object");
|
|
8311
|
-
const obj = parsed;
|
|
8290
|
+
const obj = parseYamlConfig(rawText, {
|
|
8291
|
+
emptyConfigText: ReportErrorCode.RtEmptyConfigText,
|
|
8292
|
+
invalidConfigYaml: ReportErrorCode.RtInvalidConfigYaml,
|
|
8293
|
+
invalidConfigStructure: ReportErrorCode.RtInvalidConfigStructure
|
|
8294
|
+
}, "Report");
|
|
8312
8295
|
if (!isRecord(obj.reports)) throw new BusinessRuleError(ReportErrorCode.RtInvalidConfigStructure, "Config must have a \"reports\" object");
|
|
8313
8296
|
const rawReports = obj.reports;
|
|
8314
8297
|
const reports = {};
|
|
@@ -8462,29 +8445,26 @@ function compareReports(local, remote) {
|
|
|
8462
8445
|
return diffs;
|
|
8463
8446
|
}
|
|
8464
8447
|
const ReportDiffDetector = { detect: (local, remote) => {
|
|
8465
|
-
|
|
8466
|
-
|
|
8467
|
-
const remoteReport = remote.reports[name];
|
|
8468
|
-
if (!remoteReport) entries.push({
|
|
8448
|
+
return buildDiffResult(detectRecordDiff(local.reports, remote.reports, {
|
|
8449
|
+
onAdded: (name, localReport) => ({
|
|
8469
8450
|
type: "added",
|
|
8470
8451
|
reportName: name,
|
|
8471
8452
|
details: `chartType: ${localReport.chartType}`
|
|
8472
|
-
})
|
|
8473
|
-
|
|
8453
|
+
}),
|
|
8454
|
+
onModified: (name, localReport, remoteReport) => {
|
|
8474
8455
|
const diffs = compareReports(localReport, remoteReport);
|
|
8475
|
-
if (diffs.length > 0)
|
|
8456
|
+
if (diffs.length > 0) return {
|
|
8476
8457
|
type: "modified",
|
|
8477
8458
|
reportName: name,
|
|
8478
8459
|
details: diffs.join(", ")
|
|
8479
|
-
}
|
|
8480
|
-
}
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8486
|
-
});
|
|
8487
|
-
return buildDiffResult(entries);
|
|
8460
|
+
};
|
|
8461
|
+
},
|
|
8462
|
+
onDeleted: (name, remoteReport) => ({
|
|
8463
|
+
type: "deleted",
|
|
8464
|
+
reportName: name,
|
|
8465
|
+
details: `chartType: ${remoteReport.chartType}`
|
|
8466
|
+
})
|
|
8467
|
+
}));
|
|
8488
8468
|
} };
|
|
8489
8469
|
|
|
8490
8470
|
//#endregion
|
|
@@ -10245,6 +10225,11 @@ var seed_default = define({
|
|
|
10245
10225
|
|
|
10246
10226
|
//#endregion
|
|
10247
10227
|
//#region src/core/domain/generalSettings/services/configParser.ts
|
|
10228
|
+
function parseOptionalBoolean(parsed, fieldName) {
|
|
10229
|
+
const value = parsed[fieldName];
|
|
10230
|
+
if (value === void 0 || value === null) return void 0;
|
|
10231
|
+
return parseStrictBoolean(value, fieldName, "Config", GeneralSettingsErrorCode.GsInvalidBooleanField);
|
|
10232
|
+
}
|
|
10248
10233
|
const VALID_THEMES = new Set([
|
|
10249
10234
|
"WHITE",
|
|
10250
10235
|
"RED",
|
|
@@ -10266,86 +10251,70 @@ const VALID_ROUNDING_MODES = new Set([
|
|
|
10266
10251
|
]);
|
|
10267
10252
|
function parseIcon(raw) {
|
|
10268
10253
|
if (!isRecord(raw)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "icon must be an object with \"type\" and \"key\" properties");
|
|
10269
|
-
|
|
10270
|
-
if (typeof obj.type !== "string" || !VALID_ICON_TYPES.has(obj.type)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidIconType, `icon.type must be PRESET or FILE, got: ${String(obj.type)}`);
|
|
10271
|
-
if (typeof obj.key !== "string" || obj.key.length === 0) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "icon must have a non-empty \"key\" property");
|
|
10254
|
+
if (typeof raw.key !== "string" || raw.key.length === 0) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "icon must have a non-empty \"key\" property");
|
|
10272
10255
|
return {
|
|
10273
|
-
type:
|
|
10274
|
-
key:
|
|
10256
|
+
type: parseEnum(raw.type, VALID_ICON_TYPES, GeneralSettingsErrorCode.GsInvalidIconType, `icon.type must be PRESET or FILE, got: ${String(raw.type)}`),
|
|
10257
|
+
key: raw.key
|
|
10275
10258
|
};
|
|
10276
10259
|
}
|
|
10277
10260
|
function parseTitleField(raw) {
|
|
10278
10261
|
if (!isRecord(raw)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "titleField must be an object with \"selectionMode\" property");
|
|
10279
|
-
const
|
|
10280
|
-
if (
|
|
10281
|
-
|
|
10282
|
-
if (obj.code !== void 0 && obj.code !== null) {
|
|
10283
|
-
if (typeof obj.code !== "string") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "titleField.code must be a string");
|
|
10262
|
+
const result = { selectionMode: parseEnum(raw.selectionMode, VALID_SELECTION_MODES, GeneralSettingsErrorCode.GsInvalidConfigStructure, `titleField.selectionMode must be AUTO or MANUAL, got: ${String(raw.selectionMode)}`) };
|
|
10263
|
+
if (raw.code !== void 0 && raw.code !== null) {
|
|
10264
|
+
if (typeof raw.code !== "string") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "titleField.code must be a string");
|
|
10284
10265
|
return {
|
|
10285
10266
|
...result,
|
|
10286
|
-
code:
|
|
10267
|
+
code: raw.code
|
|
10287
10268
|
};
|
|
10288
10269
|
}
|
|
10289
10270
|
return result;
|
|
10290
10271
|
}
|
|
10291
10272
|
function parseNumberPrecision(raw) {
|
|
10292
10273
|
if (!isRecord(raw)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "numberPrecision must be an object");
|
|
10293
|
-
|
|
10294
|
-
if (
|
|
10295
|
-
if (typeof
|
|
10296
|
-
if (
|
|
10274
|
+
if (typeof raw.digits !== "number") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "numberPrecision.digits must be a number");
|
|
10275
|
+
if (!Number.isInteger(raw.digits) || raw.digits < 0) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidNumberPrecision, `numberPrecision.digits must be a non-negative integer, got: ${raw.digits}`);
|
|
10276
|
+
if (typeof raw.decimalPlaces !== "number") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "numberPrecision.decimalPlaces must be a number");
|
|
10277
|
+
if (!Number.isInteger(raw.decimalPlaces) || raw.decimalPlaces < 0) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidNumberPrecision, `numberPrecision.decimalPlaces must be a non-negative integer, got: ${raw.decimalPlaces}`);
|
|
10297
10278
|
return {
|
|
10298
|
-
digits:
|
|
10299
|
-
decimalPlaces:
|
|
10300
|
-
roundingMode:
|
|
10279
|
+
digits: raw.digits,
|
|
10280
|
+
decimalPlaces: raw.decimalPlaces,
|
|
10281
|
+
roundingMode: parseEnum(raw.roundingMode, VALID_ROUNDING_MODES, GeneralSettingsErrorCode.GsInvalidConfigStructure, `numberPrecision.roundingMode must be HALF_EVEN, UP, or DOWN, got: ${String(raw.roundingMode)}`)
|
|
10301
10282
|
};
|
|
10302
10283
|
}
|
|
10303
10284
|
const GeneralSettingsConfigParser = { parse: (rawText) => {
|
|
10304
|
-
|
|
10305
|
-
|
|
10306
|
-
|
|
10307
|
-
|
|
10308
|
-
}
|
|
10309
|
-
throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
10310
|
-
}
|
|
10311
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "Config must be a YAML object");
|
|
10312
|
-
const obj = parsed;
|
|
10285
|
+
const parsed = parseYamlConfig(rawText, {
|
|
10286
|
+
emptyConfigText: GeneralSettingsErrorCode.GsEmptyConfigText,
|
|
10287
|
+
invalidConfigYaml: GeneralSettingsErrorCode.GsInvalidConfigYaml,
|
|
10288
|
+
invalidConfigStructure: GeneralSettingsErrorCode.GsInvalidConfigStructure
|
|
10289
|
+
}, "General settings");
|
|
10313
10290
|
let name;
|
|
10314
|
-
if (
|
|
10315
|
-
if (typeof
|
|
10316
|
-
name =
|
|
10291
|
+
if (parsed.name !== void 0 && parsed.name !== null) {
|
|
10292
|
+
if (typeof parsed.name !== "string") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "name must be a string");
|
|
10293
|
+
name = parsed.name;
|
|
10317
10294
|
}
|
|
10318
10295
|
let description;
|
|
10319
|
-
if (
|
|
10320
|
-
if (typeof
|
|
10321
|
-
description =
|
|
10296
|
+
if (parsed.description !== void 0 && parsed.description !== null) {
|
|
10297
|
+
if (typeof parsed.description !== "string") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "description must be a string");
|
|
10298
|
+
description = parsed.description;
|
|
10322
10299
|
}
|
|
10323
10300
|
let icon;
|
|
10324
|
-
if (
|
|
10301
|
+
if (parsed.icon !== void 0 && parsed.icon !== null) icon = parseIcon(parsed.icon);
|
|
10325
10302
|
let theme;
|
|
10326
|
-
if (
|
|
10327
|
-
if (typeof obj.theme !== "string" || !VALID_THEMES.has(obj.theme)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidTheme, `theme must be WHITE, RED, GREEN, BLUE, YELLOW, BLACK, CLIPBOARD, BINDER, PENCIL, or CLIPS, got: ${String(obj.theme)}`);
|
|
10328
|
-
theme = obj.theme;
|
|
10329
|
-
}
|
|
10303
|
+
if (parsed.theme !== void 0 && parsed.theme !== null) theme = parseEnum(parsed.theme, VALID_THEMES, GeneralSettingsErrorCode.GsInvalidTheme, `theme must be WHITE, RED, GREEN, BLUE, YELLOW, BLACK, CLIPBOARD, BINDER, PENCIL, or CLIPS, got: ${String(parsed.theme)}`);
|
|
10330
10304
|
let titleField;
|
|
10331
|
-
if (
|
|
10332
|
-
|
|
10333
|
-
|
|
10334
|
-
|
|
10335
|
-
|
|
10336
|
-
|
|
10337
|
-
if (obj.enableComments !== void 0 && obj.enableComments !== null) enableComments = Boolean(obj.enableComments);
|
|
10338
|
-
let enableDuplicateRecord;
|
|
10339
|
-
if (obj.enableDuplicateRecord !== void 0 && obj.enableDuplicateRecord !== null) enableDuplicateRecord = Boolean(obj.enableDuplicateRecord);
|
|
10340
|
-
let enableInlineRecordEditing;
|
|
10341
|
-
if (obj.enableInlineRecordEditing !== void 0 && obj.enableInlineRecordEditing !== null) enableInlineRecordEditing = Boolean(obj.enableInlineRecordEditing);
|
|
10305
|
+
if (parsed.titleField !== void 0 && parsed.titleField !== null) titleField = parseTitleField(parsed.titleField);
|
|
10306
|
+
const enableThumbnails = parseOptionalBoolean(parsed, "enableThumbnails");
|
|
10307
|
+
const enableBulkDeletion = parseOptionalBoolean(parsed, "enableBulkDeletion");
|
|
10308
|
+
const enableComments = parseOptionalBoolean(parsed, "enableComments");
|
|
10309
|
+
const enableDuplicateRecord = parseOptionalBoolean(parsed, "enableDuplicateRecord");
|
|
10310
|
+
const enableInlineRecordEditing = parseOptionalBoolean(parsed, "enableInlineRecordEditing");
|
|
10342
10311
|
let numberPrecision;
|
|
10343
|
-
if (
|
|
10312
|
+
if (parsed.numberPrecision !== void 0 && parsed.numberPrecision !== null) numberPrecision = parseNumberPrecision(parsed.numberPrecision);
|
|
10344
10313
|
let firstMonthOfFiscalYear;
|
|
10345
|
-
if (
|
|
10346
|
-
if (typeof
|
|
10347
|
-
if (
|
|
10348
|
-
firstMonthOfFiscalYear =
|
|
10314
|
+
if (parsed.firstMonthOfFiscalYear !== void 0 && parsed.firstMonthOfFiscalYear !== null) {
|
|
10315
|
+
if (typeof parsed.firstMonthOfFiscalYear !== "number") throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, "firstMonthOfFiscalYear must be a number");
|
|
10316
|
+
if (parsed.firstMonthOfFiscalYear < 1 || parsed.firstMonthOfFiscalYear > 12 || !Number.isInteger(parsed.firstMonthOfFiscalYear)) throw new BusinessRuleError(GeneralSettingsErrorCode.GsInvalidConfigStructure, `firstMonthOfFiscalYear must be an integer between 1 and 12, got: ${parsed.firstMonthOfFiscalYear}`);
|
|
10317
|
+
firstMonthOfFiscalYear = parsed.firstMonthOfFiscalYear;
|
|
10349
10318
|
}
|
|
10350
10319
|
return {
|
|
10351
10320
|
...name !== void 0 ? { name } : {},
|
|
@@ -10527,11 +10496,14 @@ function compareConfigs(local, remote) {
|
|
|
10527
10496
|
details: `${rv} -> ${lv}`
|
|
10528
10497
|
});
|
|
10529
10498
|
}
|
|
10499
|
+
function formatValue(v) {
|
|
10500
|
+
return v === void 0 ? "(none)" : JSON.stringify(v);
|
|
10501
|
+
}
|
|
10530
10502
|
function compareDeepEqual(field, l, r) {
|
|
10531
10503
|
if (!deepEqual(l, r)) entries.push({
|
|
10532
10504
|
type: "modified",
|
|
10533
10505
|
field,
|
|
10534
|
-
details: `${
|
|
10506
|
+
details: `${formatValue(r)} -> ${formatValue(l)}`
|
|
10535
10507
|
});
|
|
10536
10508
|
}
|
|
10537
10509
|
compareString("name", local.name, remote.name, DEFAULT_STRING);
|
|
@@ -10593,39 +10565,43 @@ var settings_default = define({
|
|
|
10593
10565
|
|
|
10594
10566
|
//#endregion
|
|
10595
10567
|
//#region src/core/domain/view/services/configParser.ts
|
|
10568
|
+
function parseDeviceType(name, raw) {
|
|
10569
|
+
if (raw === void 0 || raw === null) return void 0;
|
|
10570
|
+
const deviceStr = String(raw);
|
|
10571
|
+
if (!isDeviceType(deviceStr)) throw new BusinessRuleError(ViewErrorCode.VwInvalidDeviceType, `View "${name}" has invalid device type: ${deviceStr}. Must be DESKTOP or ANY`);
|
|
10572
|
+
return deviceStr;
|
|
10573
|
+
}
|
|
10596
10574
|
function parseViewConfig(name, raw) {
|
|
10597
10575
|
if (!isRecord(raw)) throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigStructure, `View "${name}" must be an object`);
|
|
10598
|
-
|
|
10599
|
-
if (typeof
|
|
10576
|
+
if (typeof raw.type !== "string" || !isViewType(raw.type)) throw new BusinessRuleError(ViewErrorCode.VwInvalidViewType, `View "${name}" has invalid type: ${String(raw.type)}. Must be LIST, CALENDAR, or CUSTOM`);
|
|
10577
|
+
if (raw.index !== void 0 && (typeof raw.index !== "number" || !Number.isInteger(raw.index) || raw.index < 0)) throw new BusinessRuleError(ViewErrorCode.VwInvalidIndex, `View "${name}" has invalid index: ${String(raw.index)}. Must be a non-negative integer`);
|
|
10578
|
+
if (raw.fields !== void 0 && !Array.isArray(raw.fields)) throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigStructure, `View "${name}" has invalid fields: must be an array`);
|
|
10579
|
+
if (raw.pager !== void 0 && typeof raw.pager !== "boolean") throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigStructure, `View "${name}" has invalid pager: must be a boolean`);
|
|
10580
|
+
const device = parseDeviceType(name, raw.device);
|
|
10600
10581
|
return {
|
|
10601
|
-
type:
|
|
10602
|
-
index: typeof
|
|
10582
|
+
type: raw.type,
|
|
10583
|
+
index: typeof raw.index === "number" ? raw.index : 0,
|
|
10603
10584
|
name,
|
|
10604
|
-
...
|
|
10605
|
-
...Array.isArray(
|
|
10606
|
-
|
|
10607
|
-
|
|
10608
|
-
|
|
10609
|
-
...
|
|
10610
|
-
...
|
|
10611
|
-
|
|
10612
|
-
|
|
10613
|
-
|
|
10614
|
-
|
|
10615
|
-
...
|
|
10616
|
-
...obj.sort !== void 0 && { sort: String(obj.sort) }
|
|
10585
|
+
...raw.builtinType !== void 0 && { builtinType: String(raw.builtinType) },
|
|
10586
|
+
...Array.isArray(raw.fields) && { fields: raw.fields.map((f, i) => {
|
|
10587
|
+
if (typeof f !== "string") throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigStructure, `View "${name}" has non-string field at index ${i}: ${String(f)}`);
|
|
10588
|
+
return f;
|
|
10589
|
+
}) },
|
|
10590
|
+
...raw.date !== void 0 && { date: String(raw.date) },
|
|
10591
|
+
...raw.title !== void 0 && { title: String(raw.title) },
|
|
10592
|
+
...raw.html !== void 0 && { html: String(raw.html) },
|
|
10593
|
+
...raw.pager !== void 0 && { pager: raw.pager },
|
|
10594
|
+
...device !== void 0 && { device },
|
|
10595
|
+
...raw.filterCond !== void 0 && { filterCond: String(raw.filterCond) },
|
|
10596
|
+
...raw.sort !== void 0 && { sort: String(raw.sort) }
|
|
10617
10597
|
};
|
|
10618
10598
|
}
|
|
10619
10599
|
const ViewConfigParser = { parse: (rawText) => {
|
|
10620
|
-
|
|
10621
|
-
|
|
10622
|
-
|
|
10623
|
-
|
|
10624
|
-
}
|
|
10625
|
-
throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigYaml, `Failed to parse YAML: ${error instanceof Error ? error.message : String(error)}`);
|
|
10626
|
-
}
|
|
10627
|
-
if (!isRecord(parsed)) throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigStructure, "Config must be a YAML object");
|
|
10628
|
-
const obj = parsed;
|
|
10600
|
+
const obj = parseYamlConfig(rawText, {
|
|
10601
|
+
emptyConfigText: ViewErrorCode.VwEmptyConfigText,
|
|
10602
|
+
invalidConfigYaml: ViewErrorCode.VwInvalidConfigYaml,
|
|
10603
|
+
invalidConfigStructure: ViewErrorCode.VwInvalidConfigStructure
|
|
10604
|
+
}, "View");
|
|
10629
10605
|
if (!isRecord(obj.views)) throw new BusinessRuleError(ViewErrorCode.VwInvalidConfigStructure, "Config must have a \"views\" object");
|
|
10630
10606
|
const viewsObj = obj.views;
|
|
10631
10607
|
const views = {};
|
|
@@ -10777,7 +10753,6 @@ var capture_default = define({
|
|
|
10777
10753
|
//#region src/core/domain/view/services/diffDetector.ts
|
|
10778
10754
|
function describeChanges(local, remote) {
|
|
10779
10755
|
const changes = [];
|
|
10780
|
-
if (local.name !== remote.name) changes.push(`name: "${remote.name}" -> "${local.name}"`);
|
|
10781
10756
|
if (local.type !== remote.type) changes.push(`type: ${remote.type} -> ${local.type}`);
|
|
10782
10757
|
if ((local.builtinType ?? "") !== (remote.builtinType ?? "")) changes.push("builtinType changed");
|
|
10783
10758
|
if (local.index !== remote.index) changes.push(`index: ${remote.index} -> ${local.index}`);
|
|
@@ -10792,29 +10767,26 @@ function describeChanges(local, remote) {
|
|
|
10792
10767
|
return changes;
|
|
10793
10768
|
}
|
|
10794
10769
|
const ViewDiffDetector = { detect: (localViews, remoteViews) => {
|
|
10795
|
-
|
|
10796
|
-
|
|
10797
|
-
const remoteView = remoteViews[name];
|
|
10798
|
-
if (remoteView === void 0) entries.push({
|
|
10770
|
+
return buildDiffResult(detectRecordDiff(localViews, remoteViews, {
|
|
10771
|
+
onAdded: (name) => ({
|
|
10799
10772
|
type: "added",
|
|
10800
10773
|
viewName: name,
|
|
10801
10774
|
details: "new view"
|
|
10802
|
-
})
|
|
10803
|
-
|
|
10775
|
+
}),
|
|
10776
|
+
onModified: (name, localView, remoteView) => {
|
|
10804
10777
|
const changes = describeChanges(localView, remoteView);
|
|
10805
|
-
if (changes.length > 0)
|
|
10778
|
+
if (changes.length > 0) return {
|
|
10806
10779
|
type: "modified",
|
|
10807
10780
|
viewName: name,
|
|
10808
10781
|
details: changes.join(", ")
|
|
10809
|
-
}
|
|
10810
|
-
}
|
|
10811
|
-
|
|
10812
|
-
|
|
10813
|
-
|
|
10814
|
-
|
|
10815
|
-
|
|
10816
|
-
});
|
|
10817
|
-
return buildDiffResult(entries);
|
|
10782
|
+
};
|
|
10783
|
+
},
|
|
10784
|
+
onDeleted: (name) => ({
|
|
10785
|
+
type: "deleted",
|
|
10786
|
+
viewName: name,
|
|
10787
|
+
details: "removed"
|
|
10788
|
+
})
|
|
10789
|
+
}));
|
|
10818
10790
|
} };
|
|
10819
10791
|
|
|
10820
10792
|
//#endregion
|