Skip to main content

AccessCommandUtils

Cmdr types and readout formatting for AccessDataService.

The formatting lives here, apart from the command that prints it, because the readout is the thing this package exists to make good -- somebody is complaining, and this is what tells you why. Pure functions over an AccessFactReport, so the exact text is unit-tested rather than eyeballed once.

Properties

OverrideValues

AccessCommandUtils.OverrideValues: {
TRUEstring,
FALSEstring,
UNRESOLVEDstring
}

The three things an override can be set to. unresolved is spelled out rather than left as an empty argument because forcing a fact to "nobody knows" is a deliberate thing to do, not a missing value.

RealmValues

AccessCommandUtils.RealmValues: {
SERVERstring,
CLIENTstring,
BOTHstring
}

Which realm a readout should come from. both is the one worth reaching for: the server and the client disagreeing about a fact is the failure this package exists to make visible, and it is invisible from either side alone.

Functions

describeValue

AccessCommandUtils.describeValue(valueboolean?) → string

How a tri-state reads to a human. Never blank -- an empty column in a readout looks like a bug in the readout rather than the answer it actually is.

parseOverrideValue

AccessCommandUtils.parseOverrideValue(textstring) → boolean?

Turns the override argument back into the value it names.

describeMetadata

AccessCommandUtils.describeMetadata(metadataany?) → string

Attribution, rendered inline. Empty when a layer attached none, so the common case stays uncluttered.

Answers the question a bare "true" cannot: which friend granted this, which gamepass was owned.

formatFactReport

AccessCommandUtils.formatFactReport(
indentstring?
) → string

One fact and every layer under it, highest priority first, with the winner marked.

Losing layers are printed rather than hidden. "Denied and the allowlist said false" and "denied and the allowlist never answered" are different problems, and only the full list tells them apart.

formatFeatureReport

AccessCommandUtils.formatFeatureReport(
subjectany--

what it was evaluated against, named on the verdict line

) → string

A feature's verdict followed by every fact it read. The whole answer to a complaint in one block.

formatContext

AccessCommandUtils.formatContext(context{[string]any}?) → {string}

A feature's non-fact inputs, one per line, sorted. Empty when the feature declared none -- a feature with no context should read exactly as it did before there was such a thing.

formatFeatureInputs

AccessCommandUtils.formatFeatureInputs(features{[string]AccessState}?) → {string}

The verdicts this feature inherited from other features, one per line, sorted.

Named and reasoned rather than reduced to true/false: "refused because bought access is switched off" and "refused because they do not own it" are different answers to the person complaining, and a boolean loses both.

formatPolicies

AccessCommandUtils.formatPolicies(policies{{
policyNamestring,
enabledboolean,
facts{string}
}}) → string

Every policy and whether it is running. A disabled policy is listed rather than hidden -- knowing a consequence exists but is switched off is most of the answer to "why did nothing happen".

formatPlayerState

AccessCommandUtils.formatPlayerState(
featureReports{AccessFeatureReport},
factReports{[string]AccessFactReport},
policies{any}?,
featureNamesNeedingSubject{string}?
) → string

Everything known about one player, in the order you actually read it: what the game concluded, then the facts those conclusions rest on. One block to paste into a bug report.

describeNameList

AccessCommandUtils.describeNameList(
names{string},
nounstring--

plural, for the count and empty forms: "facts", "policies"

) → string

How a list of names reads back in a confirmation. Names them while there are few enough to check at a glance, and counts them once naming them would be a wall -- which is exactly what * produces.

Sorted, because Cmdr builds a list argument by iterating its dedupe table: the order it hands back is hash order, not the order anybody typed.

parseSubject

AccessCommandUtils.parseSubject(textstring?) → any

Turns what somebody typed into the subject a per-thing feature is evaluated against.

Numeric text becomes a number, because the subjects that actually get typed are ids -- a world index, a chapter -- and a feature comparing subject == 3 would silently deny for "3". Anything else is passed through as the string it was. Empty means no subject.

describeSubject

AccessCommandUtils.describeSubject(subjectany) → string

How a subject reads on a verdict line. Empty when there is none, because most features never take one and "(no subject)" on every line would read as a missing input rather than as a feature that has no such input. Where the absence does matter -- a whole-player dump, where a per-thing gate is being shown in the one form nobody needs -- AccessCommandUtils.formatPlayerState says so once instead.

collectPlayerState

AccessCommandUtils.collectPlayerState(
accessDataServiceAccessDataService,
accessPolicyServiceAccessPolicyService,
playerPlayer
) → {
featureReports{AccessFeatureReport},
factReports{[string]AccessFactReport},
policies{any}
}

Everything a readout needs about one player, gathered from whichever realm this runs on.

Shared rather than written twice, because the whole value of showing the client's view next to the server's is that a difference between them is a real difference and not two formatters disagreeing.

The result is plain tables so it can be sent over remoting for exactly that comparison.

formatCollectedPlayerState

AccessCommandUtils.formatCollectedPlayerState(collectedany) → string

Renders what AccessCommandUtils.collectPlayerState gathered.

registerTypes

AccessCommandUtils.registerTypes(
cmdrany,
accessDataServiceAccessDataService,
getPolicyNames(() → {string})?
) → ()

Registers the fact-name and override-value argument types. Called on both realms -- the client needs them for autocomplete, the server to validate.

getPolicyNames is optional only as a fallback. Both realms register policies, so both realms should pass it -- without it the argument accepts whatever is typed and suggests nothing.

Show raw api
{
    "functions": [
        {
            "name": "describeValue",
            "desc": "How a tri-state reads to a human. Never blank -- an empty column in a readout looks like a bug in the\nreadout rather than the answer it actually is.",
            "params": [
                {
                    "name": "value",
                    "desc": "",
                    "lua_type": "boolean?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 71,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "parseOverrideValue",
            "desc": "Turns the override argument back into the value it names.",
            "params": [
                {
                    "name": "text",
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean?"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 87,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "describeMetadata",
            "desc": "Attribution, rendered inline. Empty when a layer attached none, so the common case stays uncluttered.\n\nAnswers the question a bare \"true\" cannot: *which* friend granted this, *which* gamepass was owned.",
            "params": [
                {
                    "name": "metadata",
                    "desc": "",
                    "lua_type": "any?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 105,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatFactReport",
            "desc": "One fact and every layer under it, highest priority first, with the winner marked.\n\nLosing layers are printed rather than hidden. \"Denied and the allowlist said false\" and \"denied and\nthe allowlist never answered\" are different problems, and only the full list tells them apart.",
            "params": [
                {
                    "name": "report",
                    "desc": "",
                    "lua_type": "AccessFactReport"
                },
                {
                    "name": "indent",
                    "desc": "",
                    "lua_type": "string?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 140,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatFeatureReport",
            "desc": "A feature's verdict followed by every fact it read. The whole answer to a complaint in one block.",
            "params": [
                {
                    "name": "report",
                    "desc": "",
                    "lua_type": "AccessFeatureReport"
                },
                {
                    "name": "subject",
                    "desc": "what it was evaluated against, named on the verdict line",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 171,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatContext",
            "desc": "A feature's non-fact inputs, one per line, sorted. Empty when the feature declared none -- a feature\nwith no context should read exactly as it did before there was such a thing.",
            "params": [
                {
                    "name": "context",
                    "desc": "",
                    "lua_type": "{ [string]: any }?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "{ string }"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 211,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatFeatureInputs",
            "desc": "The verdicts this feature inherited from other features, one per line, sorted.\n\nNamed and reasoned rather than reduced to true/false: \"refused because bought access is switched off\"\nand \"refused because they do not own it\" are different answers to the person complaining, and a\nboolean loses both.",
            "params": [
                {
                    "name": "features",
                    "desc": "",
                    "lua_type": "{ [string]: AccessState }?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "{ string }"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 240,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatPolicies",
            "desc": "Every policy and whether it is running. A disabled policy is listed rather than hidden -- knowing a\nconsequence exists but is switched off is most of the answer to \"why did nothing happen\".",
            "params": [
                {
                    "name": "policies",
                    "desc": "",
                    "lua_type": "{ { policyName: string, enabled: boolean, facts: { string } } }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 270,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatPlayerState",
            "desc": "Everything known about one player, in the order you actually read it: what the game concluded, then\nthe facts those conclusions rest on. One block to paste into a bug report.",
            "params": [
                {
                    "name": "featureReports",
                    "desc": "",
                    "lua_type": "{ AccessFeatureReport }"
                },
                {
                    "name": "factReports",
                    "desc": "",
                    "lua_type": "{ [string]: AccessFactReport }"
                },
                {
                    "name": "policies",
                    "desc": "",
                    "lua_type": "{ any }?"
                },
                {
                    "name": "featureNamesNeedingSubject",
                    "desc": "",
                    "lua_type": "{ string }?\n"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 300,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "describeNameList",
            "desc": "How a list of names reads back in a confirmation. Names them while there are few enough to check at a\nglance, and counts them once naming them would be a wall -- which is exactly what `*` produces.\n\nSorted, because Cmdr builds a list argument by iterating its dedupe table: the order it hands back is\nhash order, not the order anybody typed.",
            "params": [
                {
                    "name": "names",
                    "desc": "",
                    "lua_type": "{ string }"
                },
                {
                    "name": "noun",
                    "desc": "plural, for the count and empty forms: \"facts\", \"policies\"",
                    "lua_type": "string"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 361,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "parseSubject",
            "desc": "Turns what somebody typed into the subject a per-thing feature is evaluated against.\n\nNumeric text becomes a number, because the subjects that actually get typed are ids -- a world index, a\nchapter -- and a feature comparing `subject == 3` would silently deny for `\"3\"`. Anything else is\npassed through as the string it was. Empty means no subject.",
            "params": [
                {
                    "name": "text",
                    "desc": "",
                    "lua_type": "string?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 384,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "describeSubject",
            "desc": "How a subject reads on a verdict line. Empty when there is none, because most features never take one\nand \"(no subject)\" on every line would read as a missing input rather than as a feature that has no\nsuch input. Where the absence does matter -- a whole-player dump, where a per-thing gate is being shown\nin the one form nobody needs -- [AccessCommandUtils.formatPlayerState] says so once instead.",
            "params": [
                {
                    "name": "subject",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 401,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "collectPlayerState",
            "desc": "Everything a readout needs about one player, gathered from whichever realm this runs on.\n\nShared rather than written twice, because the whole value of showing the client's view next to the\nserver's is that a difference between them is a real difference and not two formatters disagreeing.\n\nThe result is plain tables so it can be sent over remoting for exactly that comparison.",
            "params": [
                {
                    "name": "accessDataService",
                    "desc": "",
                    "lua_type": "AccessDataService"
                },
                {
                    "name": "accessPolicyService",
                    "desc": "",
                    "lua_type": "AccessPolicyService"
                },
                {
                    "name": "player",
                    "desc": "",
                    "lua_type": "Player"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "{ featureReports: { AccessFeatureReport }, factReports: { [string]: AccessFactReport }, policies: { any } }"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 422,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "formatCollectedPlayerState",
            "desc": "Renders what [AccessCommandUtils.collectPlayerState] gathered.",
            "params": [
                {
                    "name": "collected",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "string"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 470,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "registerTypes",
            "desc": "Registers the fact-name and override-value argument types. Called on both realms -- the client needs\nthem for autocomplete, the server to validate.\n\n`getPolicyNames` is optional only as a fallback. Both realms register policies, so both realms should\npass it -- without it the argument accepts whatever is typed and suggests nothing.",
            "params": [
                {
                    "name": "cmdr",
                    "desc": "",
                    "lua_type": "any"
                },
                {
                    "name": "accessDataService",
                    "desc": "",
                    "lua_type": "AccessDataService"
                },
                {
                    "name": "getPolicyNames",
                    "desc": "",
                    "lua_type": "(() -> { string })?"
                }
            ],
            "returns": [],
            "function_type": "static",
            "source": {
                "line": 490,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        }
    ],
    "properties": [
        {
            "name": "OverrideValues",
            "desc": "The three things an override can be set to. `unresolved` is spelled out rather than left as an empty\nargument because forcing a fact to \"nobody knows\" is a deliberate thing to do, not a missing value.",
            "lua_type": "{ TRUE: string, FALSE: string, UNRESOLVED: string }",
            "source": {
                "line": 21,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        },
        {
            "name": "RealmValues",
            "desc": "Which realm a readout should come from. `both` is the one worth reaching for: the server and the\nclient disagreeing about a fact is the failure this package exists to make visible, and it is\ninvisible from either side alone.",
            "lua_type": "{ SERVER: string, CLIENT: string, BOTH: string }",
            "source": {
                "line": 34,
                "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
            }
        }
    ],
    "types": [],
    "name": "AccessCommandUtils",
    "desc": "Cmdr types and readout formatting for [AccessDataService].\n\nThe formatting lives here, apart from the command that prints it, because the readout is the thing\nthis package exists to make good -- somebody is complaining, and this is what tells you why. Pure\nfunctions over an [AccessFactReport], so the exact text is unit-tested rather than eyeballed once.",
    "source": {
        "line": 11,
        "path": "src/access/src/Shared/Commands/AccessCommandUtils.lua"
    }
}