@prorigo/protrak-forge 0.4.1 → 0.4.2
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/bin/protrak-forge.js +139 -29
- package/package.json +1 -1
package/bin/protrak-forge.js
CHANGED
|
@@ -15672,6 +15672,14 @@ var LocalSchemaProvider = class {
|
|
|
15672
15672
|
invalidateRules() {
|
|
15673
15673
|
this._rules = null;
|
|
15674
15674
|
}
|
|
15675
|
+
/** Force a re-read of types on next access. */
|
|
15676
|
+
invalidateTypes() {
|
|
15677
|
+
this._types = null;
|
|
15678
|
+
}
|
|
15679
|
+
/** Force a re-read of attributes on next access. */
|
|
15680
|
+
invalidateAttributes() {
|
|
15681
|
+
this._attributes = null;
|
|
15682
|
+
}
|
|
15675
15683
|
// ── Public API ────────────────────────────────────────────────────────────
|
|
15676
15684
|
listTypes() {
|
|
15677
15685
|
return Object.entries(this.types).map(([name, typeData]) => ({
|
|
@@ -17948,7 +17956,7 @@ function getClient() {
|
|
|
17948
17956
|
}
|
|
17949
17957
|
|
|
17950
17958
|
// src/version.ts
|
|
17951
|
-
var PACKAGE_VERSION = "0.4.
|
|
17959
|
+
var PACKAGE_VERSION = "0.4.2";
|
|
17952
17960
|
|
|
17953
17961
|
// src/tools/_schema-write-utils.ts
|
|
17954
17962
|
var fs4 = __toESM(require("fs"));
|
|
@@ -22596,6 +22604,50 @@ var EXAMPLES = [
|
|
|
22596
22604
|
}
|
|
22597
22605
|
]
|
|
22598
22606
|
}
|
|
22607
|
+
},
|
|
22608
|
+
{
|
|
22609
|
+
intent: "Current user's roles include 'Manager'. UserRoles context: attributeName is omitted entirely; Contains takes only firstValue.",
|
|
22610
|
+
rule: {
|
|
22611
|
+
name: "CurrentUserIsManager",
|
|
22612
|
+
attributeFilterGroup: [
|
|
22613
|
+
{
|
|
22614
|
+
operator: "None",
|
|
22615
|
+
attributeFilterConditions: [
|
|
22616
|
+
{
|
|
22617
|
+
attributeContext: "UserRoles",
|
|
22618
|
+
condition: "Contains",
|
|
22619
|
+
firstValue: { valueType: "Static", value: "Manager" },
|
|
22620
|
+
operator: "None"
|
|
22621
|
+
}
|
|
22622
|
+
]
|
|
22623
|
+
}
|
|
22624
|
+
]
|
|
22625
|
+
}
|
|
22626
|
+
},
|
|
22627
|
+
{
|
|
22628
|
+
intent: "Visible when current user is the Creator OR has the 'Manager' role. Mixes UserRoles + Instance contexts in a single group joined by Or.",
|
|
22629
|
+
rule: {
|
|
22630
|
+
name: "VisibleToManagerOrCreator",
|
|
22631
|
+
attributeFilterGroup: [
|
|
22632
|
+
{
|
|
22633
|
+
operator: "None",
|
|
22634
|
+
attributeFilterConditions: [
|
|
22635
|
+
{
|
|
22636
|
+
attributeContext: "UserRoles",
|
|
22637
|
+
condition: "Contains",
|
|
22638
|
+
firstValue: { valueType: "Static", value: "Manager" },
|
|
22639
|
+
operator: "Or"
|
|
22640
|
+
},
|
|
22641
|
+
{
|
|
22642
|
+
attributeName: "Creator",
|
|
22643
|
+
attributeContext: "Instance",
|
|
22644
|
+
condition: "ContextUser",
|
|
22645
|
+
operator: "None"
|
|
22646
|
+
}
|
|
22647
|
+
]
|
|
22648
|
+
}
|
|
22649
|
+
]
|
|
22650
|
+
}
|
|
22599
22651
|
}
|
|
22600
22652
|
];
|
|
22601
22653
|
var DYNAMIC_VALUE_RULES = {
|
|
@@ -22709,7 +22761,7 @@ var CONDITION_INPUT_SCHEMA = {
|
|
|
22709
22761
|
},
|
|
22710
22762
|
attribute_name: {
|
|
22711
22763
|
type: "string",
|
|
22712
|
-
description: "PascalCase attribute name. Required for Instance and User contexts.
|
|
22764
|
+
description: "PascalCase attribute name. Required for Instance and User contexts. OMIT this key entirely for UserRoles context (it evaluates the current user's roles). Do NOT send empty string '' \u2014 leave the key out."
|
|
22713
22765
|
},
|
|
22714
22766
|
condition: {
|
|
22715
22767
|
type: "string",
|
|
@@ -22717,11 +22769,11 @@ var CONDITION_INPUT_SCHEMA = {
|
|
|
22717
22769
|
},
|
|
22718
22770
|
first_value: {
|
|
22719
22771
|
...VALUE_INPUT_SCHEMA,
|
|
22720
|
-
description: "First value
|
|
22772
|
+
description: "First value of the condition. Required for value-bearing conditions (Equals, Contains, GreaterThan, Between, In, etc.). OMIT this key entirely for valueless conditions: IsEmpty, IsNotEmpty, Today, LastOneWeek, LastOneMonth, LastOneYear, NextWeek, NextOneMonth, NextOneYear, ContextUser. Do NOT send `null` or `{value: ''}` \u2014 leave the key out of the JSON object."
|
|
22721
22773
|
},
|
|
22722
22774
|
second_value: {
|
|
22723
22775
|
...VALUE_INPUT_SCHEMA,
|
|
22724
|
-
description: "Second value.
|
|
22776
|
+
description: "Second value. Only valid for 'Between'. OMIT this key entirely for every other condition (including Contains, Equals, In, IsEmpty, ContextUser, etc.). Do NOT send `null` or `{value: ''}` \u2014 leave the key out of the JSON object."
|
|
22725
22777
|
},
|
|
22726
22778
|
operator: {
|
|
22727
22779
|
type: "string",
|
|
@@ -22777,6 +22829,49 @@ var TOOL_DEF29 = {
|
|
|
22777
22829
|
required: ["name", "attribute_filter_groups"]
|
|
22778
22830
|
}
|
|
22779
22831
|
};
|
|
22832
|
+
function normalizeValue(v) {
|
|
22833
|
+
if (v === void 0 || v === null) return void 0;
|
|
22834
|
+
if (typeof v !== "object") return v;
|
|
22835
|
+
const obj = v;
|
|
22836
|
+
if (typeof obj["value"] === "string" && obj["value"].length === 0) return void 0;
|
|
22837
|
+
return obj;
|
|
22838
|
+
}
|
|
22839
|
+
function normalizeCondition(rc) {
|
|
22840
|
+
const attrName = rc["attribute_name"];
|
|
22841
|
+
return {
|
|
22842
|
+
attribute_context: rc["attribute_context"],
|
|
22843
|
+
attribute_name: typeof attrName === "string" && attrName.length > 0 ? attrName : void 0,
|
|
22844
|
+
condition: rc["condition"],
|
|
22845
|
+
first_value: normalizeValue(rc["first_value"]),
|
|
22846
|
+
second_value: normalizeValue(rc["second_value"]),
|
|
22847
|
+
operator: rc["operator"]
|
|
22848
|
+
};
|
|
22849
|
+
}
|
|
22850
|
+
function expectedConditionShape(cond) {
|
|
22851
|
+
const shape = {
|
|
22852
|
+
attribute_context: cond.attribute_context
|
|
22853
|
+
};
|
|
22854
|
+
if (cond.attribute_context !== "UserRoles") {
|
|
22855
|
+
shape["attribute_name"] = cond.attribute_name ?? "<AttributeName>";
|
|
22856
|
+
}
|
|
22857
|
+
shape["condition"] = cond.condition;
|
|
22858
|
+
if (RANGE_CONDITIONS.has(cond.condition)) {
|
|
22859
|
+
shape["first_value"] = { value_type: "Static", value: "<from>" };
|
|
22860
|
+
shape["second_value"] = { value_type: "Static", value: "<to>" };
|
|
22861
|
+
} else if (!VALUE_LESS_CONDITIONS.has(cond.condition)) {
|
|
22862
|
+
shape["first_value"] = { value_type: "Static", value: "<value>" };
|
|
22863
|
+
}
|
|
22864
|
+
shape["operator"] = cond.operator;
|
|
22865
|
+
return shape;
|
|
22866
|
+
}
|
|
22867
|
+
function conditionShapeHints(cond) {
|
|
22868
|
+
return {
|
|
22869
|
+
expected_shape: expectedConditionShape(cond),
|
|
22870
|
+
valueless_conditions: [...VALUE_LESS_CONDITIONS].sort(),
|
|
22871
|
+
range_conditions: [...RANGE_CONDITIONS].sort(),
|
|
22872
|
+
hint: 'Send the value-bearing keys ONLY when needed. To "omit" a key, leave it out of the JSON entirely \u2014 do not send null or { value: "" }.'
|
|
22873
|
+
};
|
|
22874
|
+
}
|
|
22780
22875
|
function validateValueShape(value, label) {
|
|
22781
22876
|
if (value === void 0) return null;
|
|
22782
22877
|
if (typeof value !== "object" || value === null) {
|
|
@@ -22805,36 +22900,42 @@ function validateDynamicValue(provider, value, label) {
|
|
|
22805
22900
|
}
|
|
22806
22901
|
function validateCondition(provider, cond, prefix) {
|
|
22807
22902
|
if (!ATTRIBUTE_CONTEXTS.includes(cond.attribute_context)) {
|
|
22808
|
-
return `${prefix}.attribute_context must be one of: ${ATTRIBUTE_CONTEXTS.join(", ")}
|
|
22903
|
+
return { error: `${prefix}.attribute_context must be one of: ${ATTRIBUTE_CONTEXTS.join(", ")}.` };
|
|
22809
22904
|
}
|
|
22810
22905
|
if (!GROUP_OPERATORS.includes(cond.operator)) {
|
|
22811
|
-
return `${prefix}.operator must be one of: ${GROUP_OPERATORS.join(", ")}
|
|
22906
|
+
return { error: `${prefix}.operator must be one of: ${GROUP_OPERATORS.join(", ")}.` };
|
|
22812
22907
|
}
|
|
22813
22908
|
if (typeof cond.condition !== "string" || !cond.condition) {
|
|
22814
|
-
return `${prefix}.condition is required
|
|
22909
|
+
return { error: `${prefix}.condition is required.` };
|
|
22815
22910
|
}
|
|
22816
22911
|
if (cond.attribute_context === "UserRoles") {
|
|
22817
22912
|
if (cond.attribute_name) {
|
|
22818
|
-
return `${prefix}.attribute_name must be omitted when attribute_context is 'UserRoles'
|
|
22913
|
+
return { error: `${prefix}.attribute_name must be omitted when attribute_context is 'UserRoles'.` };
|
|
22819
22914
|
}
|
|
22820
22915
|
if (!USER_ROLES_CONDITIONS.includes(cond.condition)) {
|
|
22821
|
-
return
|
|
22916
|
+
return {
|
|
22917
|
+
error: `${prefix}.condition '${cond.condition}' is not valid for UserRoles context. Valid: ${USER_ROLES_CONDITIONS.join(", ")}.`
|
|
22918
|
+
};
|
|
22822
22919
|
}
|
|
22823
22920
|
} else {
|
|
22824
22921
|
if (!cond.attribute_name) {
|
|
22825
|
-
return `${prefix}.attribute_name is required for attribute_context='${cond.attribute_context}'
|
|
22922
|
+
return { error: `${prefix}.attribute_name is required for attribute_context='${cond.attribute_context}'.` };
|
|
22826
22923
|
}
|
|
22827
22924
|
if (!isPascalCase(cond.attribute_name)) {
|
|
22828
|
-
return `${prefix}.${pascalCaseError("attribute_name", cond.attribute_name)}
|
|
22925
|
+
return { error: `${prefix}.${pascalCaseError("attribute_name", cond.attribute_name)}` };
|
|
22829
22926
|
}
|
|
22830
22927
|
if (cond.attribute_context === "Instance") {
|
|
22831
22928
|
const attrType = resolveInstanceAttributeType(provider, cond.attribute_name);
|
|
22832
22929
|
if (!attrType) {
|
|
22833
|
-
return
|
|
22930
|
+
return {
|
|
22931
|
+
error: `${prefix} references Instance attribute '${cond.attribute_name}' which does not exist in the workspace. Add the attribute (or use a basic attribute name like Name/State/Created/Creator) before generating this rule.`
|
|
22932
|
+
};
|
|
22834
22933
|
}
|
|
22835
22934
|
const validConditions = CONDITIONS_BY_ATTR_TYPE[attrType] ?? CONDITIONS_BY_ATTR_TYPE["Text"];
|
|
22836
22935
|
if (!validConditions.includes(cond.condition)) {
|
|
22837
|
-
return
|
|
22936
|
+
return {
|
|
22937
|
+
error: `${prefix}.condition '${cond.condition}' is not valid for Instance attribute '${cond.attribute_name}' (type=${attrType}). Valid conditions: ${validConditions.join(", ")}.`
|
|
22938
|
+
};
|
|
22838
22939
|
}
|
|
22839
22940
|
} else {
|
|
22840
22941
|
const acceptable = /* @__PURE__ */ new Set([
|
|
@@ -22845,7 +22946,9 @@ function validateCondition(provider, cond, prefix) {
|
|
|
22845
22946
|
...CONDITIONS_BY_ATTR_TYPE["Boolean"]
|
|
22846
22947
|
]);
|
|
22847
22948
|
if (!acceptable.has(cond.condition)) {
|
|
22848
|
-
return
|
|
22949
|
+
return {
|
|
22950
|
+
error: `${prefix}.condition '${cond.condition}' is not recognised for User-context conditions.`
|
|
22951
|
+
};
|
|
22849
22952
|
}
|
|
22850
22953
|
}
|
|
22851
22954
|
}
|
|
@@ -22855,18 +22958,30 @@ function validateCondition(provider, cond, prefix) {
|
|
|
22855
22958
|
const hasSecond = cond.second_value !== void 0;
|
|
22856
22959
|
if (valueless) {
|
|
22857
22960
|
if (hasFirst || hasSecond) {
|
|
22858
|
-
return
|
|
22961
|
+
return {
|
|
22962
|
+
error: `${prefix}.condition '${cond.condition}' takes no value(s); omit first_value and second_value entirely.`,
|
|
22963
|
+
extras: conditionShapeHints(cond)
|
|
22964
|
+
};
|
|
22859
22965
|
}
|
|
22860
22966
|
} else if (ranged) {
|
|
22861
22967
|
if (!hasFirst || !hasSecond) {
|
|
22862
|
-
return
|
|
22968
|
+
return {
|
|
22969
|
+
error: `${prefix}.condition '${cond.condition}' requires BOTH first_value and second_value.`,
|
|
22970
|
+
extras: conditionShapeHints(cond)
|
|
22971
|
+
};
|
|
22863
22972
|
}
|
|
22864
22973
|
} else {
|
|
22865
22974
|
if (!hasFirst) {
|
|
22866
|
-
return
|
|
22975
|
+
return {
|
|
22976
|
+
error: `${prefix}.condition '${cond.condition}' requires first_value.`,
|
|
22977
|
+
extras: conditionShapeHints(cond)
|
|
22978
|
+
};
|
|
22867
22979
|
}
|
|
22868
22980
|
if (hasSecond) {
|
|
22869
|
-
return
|
|
22981
|
+
return {
|
|
22982
|
+
error: `${prefix}.condition '${cond.condition}' takes only first_value; omit second_value entirely (do not send null or empty value).`,
|
|
22983
|
+
extras: conditionShapeHints(cond)
|
|
22984
|
+
};
|
|
22870
22985
|
}
|
|
22871
22986
|
}
|
|
22872
22987
|
for (const [v, lbl] of [
|
|
@@ -22874,10 +22989,10 @@ function validateCondition(provider, cond, prefix) {
|
|
|
22874
22989
|
[cond.second_value, `${prefix}.second_value`]
|
|
22875
22990
|
]) {
|
|
22876
22991
|
const shapeErr = validateValueShape(v, lbl);
|
|
22877
|
-
if (shapeErr) return shapeErr;
|
|
22992
|
+
if (shapeErr) return { error: shapeErr };
|
|
22878
22993
|
if (v) {
|
|
22879
22994
|
const dynErr = validateDynamicValue(provider, v, lbl);
|
|
22880
|
-
if (dynErr) return dynErr;
|
|
22995
|
+
if (dynErr) return { error: dynErr };
|
|
22881
22996
|
}
|
|
22882
22997
|
}
|
|
22883
22998
|
return null;
|
|
@@ -22936,16 +23051,9 @@ function handle29(provider, args) {
|
|
|
22936
23051
|
if (typeof rc !== "object" || rc === null) {
|
|
22937
23052
|
return errorResponse(`attribute_filter_groups[${gi}].conditions[${ci}] must be an object.`);
|
|
22938
23053
|
}
|
|
22939
|
-
const cond =
|
|
22940
|
-
attribute_context: rc["attribute_context"],
|
|
22941
|
-
attribute_name: rc["attribute_name"],
|
|
22942
|
-
condition: rc["condition"],
|
|
22943
|
-
first_value: rc["first_value"],
|
|
22944
|
-
second_value: rc["second_value"],
|
|
22945
|
-
operator: rc["operator"]
|
|
22946
|
-
};
|
|
23054
|
+
const cond = normalizeCondition(rc);
|
|
22947
23055
|
const err = validateCondition(provider, cond, `attribute_filter_groups[${gi}].conditions[${ci}]`);
|
|
22948
|
-
if (err) return errorResponse(err);
|
|
23056
|
+
if (err) return errorResponse(err.error, err.extras);
|
|
22949
23057
|
conditions.push(cond);
|
|
22950
23058
|
}
|
|
22951
23059
|
groups.push({ operator: raw["operator"], conditions });
|
|
@@ -23058,6 +23166,8 @@ var TOOL_DEF30 = {
|
|
|
23058
23166
|
}
|
|
23059
23167
|
};
|
|
23060
23168
|
function ruleExists(provider, ruleName) {
|
|
23169
|
+
if (provider.rules[ruleName]) return true;
|
|
23170
|
+
provider.invalidateRules();
|
|
23061
23171
|
return !!provider.rules[ruleName];
|
|
23062
23172
|
}
|
|
23063
23173
|
function findFormField(formData, attrName, containerId) {
|
package/package.json
CHANGED