@xano/xanoscript-language-server 12.17.0 → 12.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,100 @@
1
+ /**
2
+ * The policy check catalogue the language server validates policies against.
3
+ *
4
+ * The platform owns the catalogue: `GET workspace/{id}/policy/check` (and `xano policy
5
+ * catalogue -o json`) answers `{items: [check...], goals, document}`: each check with its id,
6
+ * label, description and param schemas, and `document`, the policy file's own fields (their types,
7
+ * value sets and defaults, retired fields, reserved blocks, the key pattern). Nothing here writes a
8
+ * check or a field down by hand. The registry starts EMPTY, and an empty registry means the
9
+ * language server checks the policy's block shape only.
10
+ *
11
+ * A host fills it:
12
+ * - Studio sends its own live answer (`source: "live"`); a check-level problem is then an
13
+ * error, because the instance refuses the same save.
14
+ * - The Node server and offline tools load the generated snapshot (`catalogueSnapshot.js`,
15
+ * `source: "snapshot"`); a check-level problem is then a warning, because the snapshot can
16
+ * be older than the instance the file is pushed to.
17
+ */
18
+
19
+ const EMPTY = Object.freeze({
20
+ checks: new Map(),
21
+ ids: [],
22
+ scopeFields: new Set(),
23
+ document: null,
24
+ source: null,
25
+ generatedAt: null,
26
+ });
27
+
28
+ let state = EMPTY;
29
+ let version = 0;
30
+
31
+ /**
32
+ * Replace the catalogue.
33
+ * @param {Object|Object[]|null} catalogue `{items, document}` as the platform serves it, Studio's
34
+ * `{checks, document}`, or a bare list of checks; null clears it
35
+ * @param {{source?: "live"|"snapshot", generatedAt?: string|null}} [options]
36
+ */
37
+ export function setPolicyCatalogue(catalogue, options = {}) {
38
+ const items = Array.isArray(catalogue)
39
+ ? catalogue
40
+ : (catalogue?.items ?? catalogue?.checks ?? []);
41
+ const checks = new Map();
42
+ for (const item of items) {
43
+ if (item && typeof item.id === "string" && item.id !== "") {
44
+ checks.set(item.id, item);
45
+ }
46
+ }
47
+ const document =
48
+ catalogue && !Array.isArray(catalogue) && catalogue.document && typeof catalogue.document === "object"
49
+ ? catalogue.document
50
+ : null;
51
+ version++;
52
+ if (checks.size === 0 && !document) {
53
+ state = EMPTY;
54
+ return;
55
+ }
56
+ // A scope field is any name the catalogue lists in some check's `scope_fields`: the shared
57
+ // params every check carries that choose which objects a rule selects.
58
+ const scopeFields = new Set();
59
+ for (const check of checks.values()) {
60
+ for (const field of check.scope_fields ?? []) {
61
+ if (field?.name) scopeFields.add(field.name);
62
+ }
63
+ }
64
+ state = Object.freeze({
65
+ checks,
66
+ ids: [...checks.keys()].sort(),
67
+ scopeFields,
68
+ document,
69
+ source: options.source === "snapshot" ? "snapshot" : "live",
70
+ generatedAt: options.generatedAt ?? catalogue?.generated_at ?? null,
71
+ });
72
+ }
73
+
74
+ /** Forget the catalogue: structural checks only. */
75
+ export function clearPolicyCatalogue() {
76
+ setPolicyCatalogue(null);
77
+ }
78
+
79
+ /**
80
+ * @returns {{checks: Map<string, Object>, ids: string[], scopeFields: Set<string>,
81
+ * document: Object|null, source: "live"|"snapshot"|null, generatedAt: string|null}}
82
+ */
83
+ export function getPolicyCatalogue() {
84
+ return state;
85
+ }
86
+
87
+ /** Whether a catalogue is loaded. */
88
+ export function hasPolicyCatalogue() {
89
+ return state.source !== null;
90
+ }
91
+
92
+ /** One check by id, or null. */
93
+ export function getPolicyCheck(id) {
94
+ return state.checks.get(id) ?? null;
95
+ }
96
+
97
+ /** Bumped on every change, so a cached parse made against an older catalogue is not reused. */
98
+ export function policyCatalogueVersion() {
99
+ return version;
100
+ }