@butlr/butlr-mcp-server 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +195 -0
- package/dist/cache/occupancy-cache.d.ts +72 -0
- package/dist/cache/occupancy-cache.d.ts.map +1 -0
- package/dist/cache/occupancy-cache.js +166 -0
- package/dist/cache/occupancy-cache.js.map +1 -0
- package/dist/cache/topology-cache.d.ts +36 -0
- package/dist/cache/topology-cache.d.ts.map +1 -0
- package/dist/cache/topology-cache.js +74 -0
- package/dist/cache/topology-cache.js.map +1 -0
- package/dist/clients/auth-client.d.ts +22 -0
- package/dist/clients/auth-client.d.ts.map +1 -0
- package/dist/clients/auth-client.js +82 -0
- package/dist/clients/auth-client.js.map +1 -0
- package/dist/clients/graphql-client.d.ts +6 -0
- package/dist/clients/graphql-client.d.ts.map +1 -0
- package/dist/clients/graphql-client.js +106 -0
- package/dist/clients/graphql-client.js.map +1 -0
- package/dist/clients/queries/topology.d.ts +36 -0
- package/dist/clients/queries/topology.d.ts.map +1 -0
- package/dist/clients/queries/topology.js +252 -0
- package/dist/clients/queries/topology.js.map +1 -0
- package/dist/clients/reporting-client.d.ts +191 -0
- package/dist/clients/reporting-client.d.ts.map +1 -0
- package/dist/clients/reporting-client.js +353 -0
- package/dist/clients/reporting-client.js.map +1 -0
- package/dist/clients/stats-client.d.ts +119 -0
- package/dist/clients/stats-client.d.ts.map +1 -0
- package/dist/clients/stats-client.js +238 -0
- package/dist/clients/stats-client.js.map +1 -0
- package/dist/clients/types.d.ts +215 -0
- package/dist/clients/types.d.ts.map +1 -0
- package/dist/clients/types.js +6 -0
- package/dist/clients/types.js.map +1 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +3 -0
- package/dist/constants.js.map +1 -0
- package/dist/errors/mcp-errors.d.ts +63 -0
- package/dist/errors/mcp-errors.d.ts.map +1 -0
- package/dist/errors/mcp-errors.js +144 -0
- package/dist/errors/mcp-errors.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/butlr-available-rooms.d.ts +49 -0
- package/dist/tools/butlr-available-rooms.d.ts.map +1 -0
- package/dist/tools/butlr-available-rooms.js +492 -0
- package/dist/tools/butlr-available-rooms.js.map +1 -0
- package/dist/tools/butlr-fetch-entity-details.d.ts +42 -0
- package/dist/tools/butlr-fetch-entity-details.d.ts.map +1 -0
- package/dist/tools/butlr-fetch-entity-details.js +276 -0
- package/dist/tools/butlr-fetch-entity-details.js.map +1 -0
- package/dist/tools/butlr-get-asset-details.d.ts +51 -0
- package/dist/tools/butlr-get-asset-details.d.ts.map +1 -0
- package/dist/tools/butlr-get-asset-details.js +391 -0
- package/dist/tools/butlr-get-asset-details.js.map +1 -0
- package/dist/tools/butlr-get-current-occupancy.d.ts +21 -0
- package/dist/tools/butlr-get-current-occupancy.d.ts.map +1 -0
- package/dist/tools/butlr-get-current-occupancy.js +126 -0
- package/dist/tools/butlr-get-current-occupancy.js.map +1 -0
- package/dist/tools/butlr-get-occupancy-timeseries.d.ts +31 -0
- package/dist/tools/butlr-get-occupancy-timeseries.d.ts.map +1 -0
- package/dist/tools/butlr-get-occupancy-timeseries.js +145 -0
- package/dist/tools/butlr-get-occupancy-timeseries.js.map +1 -0
- package/dist/tools/butlr-hardware-snapshot.d.ts +55 -0
- package/dist/tools/butlr-hardware-snapshot.d.ts.map +1 -0
- package/dist/tools/butlr-hardware-snapshot.js +556 -0
- package/dist/tools/butlr-hardware-snapshot.js.map +1 -0
- package/dist/tools/butlr-list-topology.d.ts +27 -0
- package/dist/tools/butlr-list-topology.d.ts.map +1 -0
- package/dist/tools/butlr-list-topology.js +241 -0
- package/dist/tools/butlr-list-topology.js.map +1 -0
- package/dist/tools/butlr-search-assets.d.ts +53 -0
- package/dist/tools/butlr-search-assets.d.ts.map +1 -0
- package/dist/tools/butlr-search-assets.js +206 -0
- package/dist/tools/butlr-search-assets.js.map +1 -0
- package/dist/tools/butlr-space-busyness.d.ts +23 -0
- package/dist/tools/butlr-space-busyness.d.ts.map +1 -0
- package/dist/tools/butlr-space-busyness.js +304 -0
- package/dist/tools/butlr-space-busyness.js.map +1 -0
- package/dist/tools/butlr-traffic-flow.d.ts +39 -0
- package/dist/tools/butlr-traffic-flow.d.ts.map +1 -0
- package/dist/tools/butlr-traffic-flow.js +369 -0
- package/dist/tools/butlr-traffic-flow.js.map +1 -0
- package/dist/types/responses.d.ts +253 -0
- package/dist/types/responses.d.ts.map +1 -0
- package/dist/types/responses.js +8 -0
- package/dist/types/responses.js.map +1 -0
- package/dist/utils/asset-flattener.d.ts +50 -0
- package/dist/utils/asset-flattener.d.ts.map +1 -0
- package/dist/utils/asset-flattener.js +131 -0
- package/dist/utils/asset-flattener.js.map +1 -0
- package/dist/utils/asset-helpers.d.ts +8 -0
- package/dist/utils/asset-helpers.d.ts.map +1 -0
- package/dist/utils/asset-helpers.js +24 -0
- package/dist/utils/asset-helpers.js.map +1 -0
- package/dist/utils/field-validator.d.ts +29 -0
- package/dist/utils/field-validator.d.ts.map +1 -0
- package/dist/utils/field-validator.js +197 -0
- package/dist/utils/field-validator.js.map +1 -0
- package/dist/utils/fuzzy-match.d.ts +29 -0
- package/dist/utils/fuzzy-match.d.ts.map +1 -0
- package/dist/utils/fuzzy-match.js +70 -0
- package/dist/utils/fuzzy-match.js.map +1 -0
- package/dist/utils/graphql-helpers.d.ts +29 -0
- package/dist/utils/graphql-helpers.d.ts.map +1 -0
- package/dist/utils/graphql-helpers.js +43 -0
- package/dist/utils/graphql-helpers.js.map +1 -0
- package/dist/utils/natural-language.d.ts +73 -0
- package/dist/utils/natural-language.d.ts.map +1 -0
- package/dist/utils/natural-language.js +172 -0
- package/dist/utils/natural-language.js.map +1 -0
- package/dist/utils/occupancy-helpers.d.ts +63 -0
- package/dist/utils/occupancy-helpers.d.ts.map +1 -0
- package/dist/utils/occupancy-helpers.js +203 -0
- package/dist/utils/occupancy-helpers.js.map +1 -0
- package/dist/utils/path-builder.d.ts +10 -0
- package/dist/utils/path-builder.d.ts.map +1 -0
- package/dist/utils/path-builder.js +34 -0
- package/dist/utils/path-builder.js.map +1 -0
- package/dist/utils/time-range-validator.d.ts +13 -0
- package/dist/utils/time-range-validator.d.ts.map +1 -0
- package/dist/utils/time-range-validator.js +65 -0
- package/dist/utils/time-range-validator.js.map +1 -0
- package/dist/utils/timezone-helpers.d.ts +49 -0
- package/dist/utils/timezone-helpers.d.ts.map +1 -0
- package/dist/utils/timezone-helpers.js +209 -0
- package/dist/utils/timezone-helpers.js.map +1 -0
- package/dist/utils/tree-formatter.d.ts +23 -0
- package/dist/utils/tree-formatter.d.ts.map +1 -0
- package/dist/utils/tree-formatter.js +258 -0
- package/dist/utils/tree-formatter.js.map +1 -0
- package/package.json +93 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for flattening hierarchical topology into searchable lists
|
|
3
|
+
*/
|
|
4
|
+
import type { Site } from "../clients/types.js";
|
|
5
|
+
export interface FlattenedAsset {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
type: "site" | "building" | "floor" | "room" | "zone" | "sensor" | "hive";
|
|
9
|
+
site_id?: string;
|
|
10
|
+
site_name?: string;
|
|
11
|
+
building_id?: string;
|
|
12
|
+
building_name?: string;
|
|
13
|
+
floor_id?: string;
|
|
14
|
+
floor_name?: string;
|
|
15
|
+
room_id?: string;
|
|
16
|
+
room_name?: string;
|
|
17
|
+
timezone?: string;
|
|
18
|
+
siteNumber?: number;
|
|
19
|
+
customID?: string;
|
|
20
|
+
org_id?: string;
|
|
21
|
+
building_number?: number;
|
|
22
|
+
capacity?: {
|
|
23
|
+
max?: number;
|
|
24
|
+
mid?: number;
|
|
25
|
+
};
|
|
26
|
+
address?: {
|
|
27
|
+
lines?: string[];
|
|
28
|
+
country?: string;
|
|
29
|
+
};
|
|
30
|
+
floorNumber?: number;
|
|
31
|
+
installation_date?: number;
|
|
32
|
+
area?: {
|
|
33
|
+
value?: number;
|
|
34
|
+
unit?: string;
|
|
35
|
+
};
|
|
36
|
+
roomType?: string;
|
|
37
|
+
coordinates?: number[][] | number[];
|
|
38
|
+
mac_address?: string;
|
|
39
|
+
mode?: "presence" | "traffic";
|
|
40
|
+
model?: string;
|
|
41
|
+
hive_serial?: string;
|
|
42
|
+
is_online?: boolean;
|
|
43
|
+
serialNumber?: string;
|
|
44
|
+
hiveVersion?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Flatten topology hierarchy into a searchable list
|
|
48
|
+
*/
|
|
49
|
+
export declare function flattenTopology(sites: Site[]): FlattenedAsset[];
|
|
50
|
+
//# sourceMappingURL=asset-flattener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-flattener.d.ts","sourceRoot":"","sources":["../../src/utils/asset-flattener.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAEhD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IAG1E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IAGnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAGhB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC1C,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAGjD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAGzC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,CAAC;IAGpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,IAAI,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,OAAO,CAAC;IAGpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,cAAc,EAAE,CAmI/D"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utilities for flattening hierarchical topology into searchable lists
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Flatten topology hierarchy into a searchable list
|
|
6
|
+
*/
|
|
7
|
+
export function flattenTopology(sites) {
|
|
8
|
+
const flattened = [];
|
|
9
|
+
for (const site of sites) {
|
|
10
|
+
// Add site
|
|
11
|
+
flattened.push({
|
|
12
|
+
id: site.id,
|
|
13
|
+
name: site.name,
|
|
14
|
+
type: "site",
|
|
15
|
+
timezone: site.timezone,
|
|
16
|
+
siteNumber: site.siteNumber,
|
|
17
|
+
customID: site.customID,
|
|
18
|
+
org_id: site.org_id,
|
|
19
|
+
});
|
|
20
|
+
// Add buildings
|
|
21
|
+
for (const building of site.buildings || []) {
|
|
22
|
+
flattened.push({
|
|
23
|
+
id: building.id,
|
|
24
|
+
name: building.name,
|
|
25
|
+
type: "building",
|
|
26
|
+
site_id: site.id,
|
|
27
|
+
site_name: site.name,
|
|
28
|
+
building_number: building.building_number || building.buildingNumber,
|
|
29
|
+
customID: building.customID,
|
|
30
|
+
capacity: building.capacity,
|
|
31
|
+
address: building.address,
|
|
32
|
+
});
|
|
33
|
+
// Add floors
|
|
34
|
+
for (const floor of building.floors || []) {
|
|
35
|
+
flattened.push({
|
|
36
|
+
id: floor.id,
|
|
37
|
+
name: floor.name,
|
|
38
|
+
type: "floor",
|
|
39
|
+
site_id: site.id,
|
|
40
|
+
site_name: site.name,
|
|
41
|
+
building_id: building.id,
|
|
42
|
+
building_name: building.name,
|
|
43
|
+
floorNumber: floor.floorNumber,
|
|
44
|
+
customID: floor.customID,
|
|
45
|
+
timezone: floor.timezone,
|
|
46
|
+
installation_date: floor.installation_date,
|
|
47
|
+
capacity: floor.capacity,
|
|
48
|
+
area: floor.area,
|
|
49
|
+
});
|
|
50
|
+
// Add rooms
|
|
51
|
+
for (const room of floor.rooms || []) {
|
|
52
|
+
flattened.push({
|
|
53
|
+
id: room.id,
|
|
54
|
+
name: room.name,
|
|
55
|
+
type: "room",
|
|
56
|
+
site_id: site.id,
|
|
57
|
+
site_name: site.name,
|
|
58
|
+
building_id: building.id,
|
|
59
|
+
building_name: building.name,
|
|
60
|
+
floor_id: floor.id,
|
|
61
|
+
floor_name: floor.name,
|
|
62
|
+
roomType: room.roomType,
|
|
63
|
+
customID: room.customID,
|
|
64
|
+
capacity: room.capacity,
|
|
65
|
+
area: room.area,
|
|
66
|
+
coordinates: room.coordinates,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
// Add zones
|
|
70
|
+
for (const zone of floor.zones || []) {
|
|
71
|
+
flattened.push({
|
|
72
|
+
id: zone.id,
|
|
73
|
+
name: zone.name,
|
|
74
|
+
type: "zone",
|
|
75
|
+
site_id: site.id,
|
|
76
|
+
site_name: site.name,
|
|
77
|
+
building_id: building.id,
|
|
78
|
+
building_name: building.name,
|
|
79
|
+
floor_id: floor.id,
|
|
80
|
+
floor_name: floor.name,
|
|
81
|
+
room_id: zone.roomID,
|
|
82
|
+
customID: zone.customID,
|
|
83
|
+
capacity: zone.capacity,
|
|
84
|
+
coordinates: zone.coordinates,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
// Add sensors
|
|
88
|
+
for (const sensor of floor.sensors || []) {
|
|
89
|
+
flattened.push({
|
|
90
|
+
id: sensor.id,
|
|
91
|
+
name: sensor.name,
|
|
92
|
+
type: "sensor",
|
|
93
|
+
site_id: site.id,
|
|
94
|
+
site_name: site.name,
|
|
95
|
+
building_id: building.id,
|
|
96
|
+
building_name: building.name,
|
|
97
|
+
floor_id: floor.id,
|
|
98
|
+
floor_name: floor.name,
|
|
99
|
+
room_id: sensor.roomID,
|
|
100
|
+
mac_address: sensor.mac_address,
|
|
101
|
+
mode: sensor.mode,
|
|
102
|
+
model: sensor.model,
|
|
103
|
+
hive_serial: sensor.hive_serial,
|
|
104
|
+
is_online: sensor.is_online,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
// Add hives
|
|
108
|
+
for (const hive of floor.hives || []) {
|
|
109
|
+
flattened.push({
|
|
110
|
+
id: hive.id,
|
|
111
|
+
name: hive.name,
|
|
112
|
+
type: "hive",
|
|
113
|
+
site_id: site.id,
|
|
114
|
+
site_name: site.name,
|
|
115
|
+
building_id: building.id,
|
|
116
|
+
building_name: building.name,
|
|
117
|
+
floor_id: floor.id,
|
|
118
|
+
floor_name: floor.name,
|
|
119
|
+
room_id: hive.roomID,
|
|
120
|
+
serialNumber: hive.serialNumber,
|
|
121
|
+
is_online: hive.isOnline || hive.is_online,
|
|
122
|
+
hiveVersion: hive.hiveVersion,
|
|
123
|
+
coordinates: hive.coordinates,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return flattened;
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=asset-flattener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-flattener.js","sourceRoot":"","sources":["../../src/utils/asset-flattener.ts"],"names":[],"mappings":"AAAA;;GAEG;AAmDH;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,MAAM,SAAS,GAAqB,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,WAAW;QACX,SAAS,CAAC,IAAI,CAAC;YACb,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,IAAI,EAAE,MAAM;YACZ,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,UAAU,EAAE,IAAI,CAAC,UAAU;YAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAC;QAEH,gBAAgB;QAChB,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,IAAI,EAAE,EAAE,CAAC;YAC5C,SAAS,CAAC,IAAI,CAAC;gBACb,EAAE,EAAE,QAAQ,CAAC,EAAE;gBACf,IAAI,EAAE,QAAQ,CAAC,IAAI;gBACnB,IAAI,EAAE,UAAU;gBAChB,OAAO,EAAE,IAAI,CAAC,EAAE;gBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;gBACpB,eAAe,EAAE,QAAQ,CAAC,eAAe,IAAI,QAAQ,CAAC,cAAc;gBACpE,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,QAAQ,EAAE,QAAQ,CAAC,QAAQ;gBAC3B,OAAO,EAAE,QAAQ,CAAC,OAAO;aAC1B,CAAC,CAAC;YAEH,aAAa;YACb,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBAC1C,SAAS,CAAC,IAAI,CAAC;oBACb,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,IAAI,EAAE,OAAO;oBACb,OAAO,EAAE,IAAI,CAAC,EAAE;oBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;oBACpB,WAAW,EAAE,QAAQ,CAAC,EAAE;oBACxB,aAAa,EAAE,QAAQ,CAAC,IAAI;oBAC5B,WAAW,EAAE,KAAK,CAAC,WAAW;oBAC9B,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,iBAAiB,EAAE,KAAK,CAAC,iBAAiB;oBAC1C,QAAQ,EAAE,KAAK,CAAC,QAAQ;oBACxB,IAAI,EAAE,KAAK,CAAC,IAAI;iBACjB,CAAC,CAAC;gBAEH,YAAY;gBACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;oBACrC,SAAS,CAAC,IAAI,CAAC;wBACb,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,IAAI,CAAC,EAAE;wBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,WAAW,EAAE,QAAQ,CAAC,EAAE;wBACxB,aAAa,EAAE,QAAQ,CAAC,IAAI;wBAC5B,QAAQ,EAAE,KAAK,CAAC,EAAE;wBAClB,UAAU,EAAE,KAAK,CAAC,IAAI;wBACtB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,WAAW,EAAE,IAAI,CAAC,WAAW;qBAC9B,CAAC,CAAC;gBACL,CAAC;gBAED,YAAY;gBACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;oBACrC,SAAS,CAAC,IAAI,CAAC;wBACb,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,IAAI,CAAC,EAAE;wBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,WAAW,EAAE,QAAQ,CAAC,EAAE;wBACxB,aAAa,EAAE,QAAQ,CAAC,IAAI;wBAC5B,QAAQ,EAAE,KAAK,CAAC,EAAE;wBAClB,UAAU,EAAE,KAAK,CAAC,IAAI;wBACtB,OAAO,EAAE,IAAI,CAAC,MAAM;wBACpB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;wBACvB,WAAW,EAAE,IAAI,CAAC,WAAW;qBAC9B,CAAC,CAAC;gBACL,CAAC;gBAED,cAAc;gBACd,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;oBACzC,SAAS,CAAC,IAAI,CAAC;wBACb,EAAE,EAAE,MAAM,CAAC,EAAE;wBACb,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,IAAI,EAAE,QAAQ;wBACd,OAAO,EAAE,IAAI,CAAC,EAAE;wBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,WAAW,EAAE,QAAQ,CAAC,EAAE;wBACxB,aAAa,EAAE,QAAQ,CAAC,IAAI;wBAC5B,QAAQ,EAAE,KAAK,CAAC,EAAE;wBAClB,UAAU,EAAE,KAAK,CAAC,IAAI;wBACtB,OAAO,EAAE,MAAM,CAAC,MAAM;wBACtB,WAAW,EAAE,MAAM,CAAC,WAAW;wBAC/B,IAAI,EAAE,MAAM,CAAC,IAAI;wBACjB,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,WAAW,EAAE,MAAM,CAAC,WAAW;wBAC/B,SAAS,EAAE,MAAM,CAAC,SAAS;qBAC5B,CAAC,CAAC;gBACL,CAAC;gBAED,YAAY;gBACZ,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;oBACrC,SAAS,CAAC,IAAI,CAAC;wBACb,EAAE,EAAE,IAAI,CAAC,EAAE;wBACX,IAAI,EAAE,IAAI,CAAC,IAAI;wBACf,IAAI,EAAE,MAAM;wBACZ,OAAO,EAAE,IAAI,CAAC,EAAE;wBAChB,SAAS,EAAE,IAAI,CAAC,IAAI;wBACpB,WAAW,EAAE,QAAQ,CAAC,EAAE;wBACxB,aAAa,EAAE,QAAQ,CAAC,IAAI;wBAC5B,QAAQ,EAAE,KAAK,CAAC,EAAE;wBAClB,UAAU,EAAE,KAAK,CAAC,IAAI;wBACtB,OAAO,EAAE,IAAI,CAAC,MAAM;wBACpB,YAAY,EAAE,IAAI,CAAC,YAAY;wBAC/B,SAAS,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,SAAS;wBAC1C,WAAW,EAAE,IAAI,CAAC,WAAW;wBAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;qBAC9B,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset helper utilities for type detection and ID parsing
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Detect asset type from ID prefix
|
|
6
|
+
*/
|
|
7
|
+
export declare function detectAssetType(id: string): "site" | "building" | "floor" | "room" | "zone" | "sensor" | "hive" | "unknown";
|
|
8
|
+
//# sourceMappingURL=asset-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/asset-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,eAAe,CAC7B,EAAE,EAAE,MAAM,GACT,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CASjF"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Asset helper utilities for type detection and ID parsing
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Detect asset type from ID prefix
|
|
6
|
+
*/
|
|
7
|
+
export function detectAssetType(id) {
|
|
8
|
+
if (id.startsWith("site_"))
|
|
9
|
+
return "site";
|
|
10
|
+
if (id.startsWith("building_"))
|
|
11
|
+
return "building";
|
|
12
|
+
if (id.startsWith("space_") || id.startsWith("floor_"))
|
|
13
|
+
return "floor";
|
|
14
|
+
if (id.startsWith("room_"))
|
|
15
|
+
return "room";
|
|
16
|
+
if (id.startsWith("zone_"))
|
|
17
|
+
return "zone";
|
|
18
|
+
if (id.startsWith("sensor_"))
|
|
19
|
+
return "sensor";
|
|
20
|
+
if (id.startsWith("hive_"))
|
|
21
|
+
return "hive";
|
|
22
|
+
return "unknown";
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=asset-helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asset-helpers.js","sourceRoot":"","sources":["../../src/utils/asset-helpers.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,UAAU,eAAe,CAC7B,EAAU;IAEV,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1C,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC;QAAE,OAAO,UAAU,CAAC;IAClD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;QAAE,OAAO,OAAO,CAAC;IACvE,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1C,IAAI,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1C,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field validation for selective entity detail fetching
|
|
3
|
+
* Validates that requested fields are valid for each entity type
|
|
4
|
+
*/
|
|
5
|
+
/** Known entity types supported by the Butlr GraphQL API */
|
|
6
|
+
export declare const ENTITY_TYPES: readonly ["site", "building", "floor", "room", "zone", "sensor", "hive"];
|
|
7
|
+
export type EntityType = (typeof ENTITY_TYPES)[number];
|
|
8
|
+
/**
|
|
9
|
+
* Default fields for each entity type (minimal set)
|
|
10
|
+
*/
|
|
11
|
+
export declare const DEFAULT_FIELDS: Record<EntityType, readonly string[]>;
|
|
12
|
+
/**
|
|
13
|
+
* Validate that requested fields are valid for an entity type
|
|
14
|
+
* Accepts both snake_case and camelCase field names
|
|
15
|
+
* @param entityType Type of entity (site, building, floor, room, zone, sensor, hive)
|
|
16
|
+
* @param requestedFields Array of field names
|
|
17
|
+
* @throws Error if any field is invalid
|
|
18
|
+
*/
|
|
19
|
+
export declare function validateFields(entityType: EntityType, requestedFields: string[]): void;
|
|
20
|
+
/**
|
|
21
|
+
* Get default fields for an entity type
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDefaultFields(entityType: EntityType): string[];
|
|
24
|
+
/**
|
|
25
|
+
* Validate and return fields (use defaults if none provided)
|
|
26
|
+
* Normalizes snake_case to camelCase for GraphQL queries
|
|
27
|
+
*/
|
|
28
|
+
export declare function getValidatedFields(entityType: EntityType, requestedFields?: string[]): string[];
|
|
29
|
+
//# sourceMappingURL=field-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-validator.d.ts","sourceRoot":"","sources":["../../src/utils/field-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,4DAA4D;AAC5D,eAAO,MAAM,YAAY,0EAQf,CAAC;AAEX,MAAM,MAAM,UAAU,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC;AA+HvD;;GAEG;AACH,eAAO,MAAM,cAAc,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAQhE,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,IAAI,CAuBtF;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM,EAAE,CAMjE;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,UAAU,EAAE,eAAe,CAAC,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAgB/F"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field validation for selective entity detail fetching
|
|
3
|
+
* Validates that requested fields are valid for each entity type
|
|
4
|
+
*/
|
|
5
|
+
/** Known entity types supported by the Butlr GraphQL API */
|
|
6
|
+
export const ENTITY_TYPES = [
|
|
7
|
+
"site",
|
|
8
|
+
"building",
|
|
9
|
+
"floor",
|
|
10
|
+
"room",
|
|
11
|
+
"zone",
|
|
12
|
+
"sensor",
|
|
13
|
+
"hive",
|
|
14
|
+
];
|
|
15
|
+
/**
|
|
16
|
+
* Field name aliases (snake_case → camelCase)
|
|
17
|
+
* GraphQL schema uses a mix of snake_case and camelCase.
|
|
18
|
+
* Some fields have aliases (e.g., floor_id → floorID).
|
|
19
|
+
*/
|
|
20
|
+
const FIELD_ALIASES = {
|
|
21
|
+
floor_id: "floorID",
|
|
22
|
+
room_id: "roomID",
|
|
23
|
+
hive_id: "hiveID",
|
|
24
|
+
sensor_id: "id", // sensor_id is deprecated, use id
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Normalize field name (convert snake_case to camelCase if alias exists)
|
|
28
|
+
*/
|
|
29
|
+
function normalizeFieldName(field) {
|
|
30
|
+
return FIELD_ALIASES[field] || field;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Valid fields for each entity type
|
|
34
|
+
* Based on GraphQL schema (mix of snake_case and camelCase)
|
|
35
|
+
*/
|
|
36
|
+
const VALID_FIELDS = {
|
|
37
|
+
site: ["id", "name", "timezone", "siteNumber", "customID", "org_id", "buildings"],
|
|
38
|
+
building: [
|
|
39
|
+
"id",
|
|
40
|
+
"name",
|
|
41
|
+
"building_number",
|
|
42
|
+
"site_id",
|
|
43
|
+
"customID",
|
|
44
|
+
"capacity",
|
|
45
|
+
"address",
|
|
46
|
+
"floors",
|
|
47
|
+
"site",
|
|
48
|
+
],
|
|
49
|
+
floor: [
|
|
50
|
+
"id",
|
|
51
|
+
"name",
|
|
52
|
+
"floorNumber",
|
|
53
|
+
"building_id",
|
|
54
|
+
"timezone",
|
|
55
|
+
"installation_date",
|
|
56
|
+
"installation_status",
|
|
57
|
+
"customID",
|
|
58
|
+
"capacity",
|
|
59
|
+
"area",
|
|
60
|
+
"rooms",
|
|
61
|
+
"zones",
|
|
62
|
+
"sensors",
|
|
63
|
+
"hives",
|
|
64
|
+
"building",
|
|
65
|
+
],
|
|
66
|
+
room: [
|
|
67
|
+
"id",
|
|
68
|
+
"name",
|
|
69
|
+
"floorID",
|
|
70
|
+
"roomType",
|
|
71
|
+
"customID",
|
|
72
|
+
"capacity",
|
|
73
|
+
"area",
|
|
74
|
+
"coordinates",
|
|
75
|
+
"rotation",
|
|
76
|
+
"note",
|
|
77
|
+
"sensors",
|
|
78
|
+
"floor",
|
|
79
|
+
],
|
|
80
|
+
zone: [
|
|
81
|
+
"id",
|
|
82
|
+
"name",
|
|
83
|
+
"floorID",
|
|
84
|
+
"roomID",
|
|
85
|
+
"customID",
|
|
86
|
+
"capacity",
|
|
87
|
+
"area",
|
|
88
|
+
"coordinates",
|
|
89
|
+
"rotation",
|
|
90
|
+
"note",
|
|
91
|
+
"sensors",
|
|
92
|
+
],
|
|
93
|
+
sensor: [
|
|
94
|
+
"id",
|
|
95
|
+
"name",
|
|
96
|
+
"mac_address",
|
|
97
|
+
"mode",
|
|
98
|
+
"model",
|
|
99
|
+
"roomID",
|
|
100
|
+
"hive_serial",
|
|
101
|
+
"is_online",
|
|
102
|
+
"is_streaming",
|
|
103
|
+
"height",
|
|
104
|
+
"center",
|
|
105
|
+
"orientation",
|
|
106
|
+
"field_of_view",
|
|
107
|
+
"door_line",
|
|
108
|
+
"in_direction",
|
|
109
|
+
"is_entrance",
|
|
110
|
+
"parallel_to_door",
|
|
111
|
+
"sensitivity",
|
|
112
|
+
"note",
|
|
113
|
+
"last_heartbeat",
|
|
114
|
+
"last_raw_message",
|
|
115
|
+
"last_occupancy_message",
|
|
116
|
+
"power_type",
|
|
117
|
+
"sensor_serial",
|
|
118
|
+
"installation_status",
|
|
119
|
+
],
|
|
120
|
+
hive: [
|
|
121
|
+
"id",
|
|
122
|
+
"name",
|
|
123
|
+
"serialNumber",
|
|
124
|
+
"floorID",
|
|
125
|
+
"roomID",
|
|
126
|
+
"isOnline",
|
|
127
|
+
"coordinates",
|
|
128
|
+
"isStreaming",
|
|
129
|
+
"hiveVersion",
|
|
130
|
+
"hiveType",
|
|
131
|
+
"note",
|
|
132
|
+
"lastHeartbeat",
|
|
133
|
+
"netPathStability",
|
|
134
|
+
"installed",
|
|
135
|
+
],
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* Default fields for each entity type (minimal set)
|
|
139
|
+
*/
|
|
140
|
+
export const DEFAULT_FIELDS = {
|
|
141
|
+
site: ["id", "name"],
|
|
142
|
+
building: ["id", "name"],
|
|
143
|
+
floor: ["id", "name", "floorNumber"],
|
|
144
|
+
room: ["id", "name"],
|
|
145
|
+
zone: ["id", "name"],
|
|
146
|
+
sensor: ["id", "mac_address"],
|
|
147
|
+
hive: ["id", "serialNumber"],
|
|
148
|
+
};
|
|
149
|
+
/**
|
|
150
|
+
* Validate that requested fields are valid for an entity type
|
|
151
|
+
* Accepts both snake_case and camelCase field names
|
|
152
|
+
* @param entityType Type of entity (site, building, floor, room, zone, sensor, hive)
|
|
153
|
+
* @param requestedFields Array of field names
|
|
154
|
+
* @throws Error if any field is invalid
|
|
155
|
+
*/
|
|
156
|
+
export function validateFields(entityType, requestedFields) {
|
|
157
|
+
const validFields = VALID_FIELDS[entityType];
|
|
158
|
+
if (!validFields) {
|
|
159
|
+
throw new Error(`Unknown entity type: ${entityType}. Valid types: ${Object.keys(VALID_FIELDS).join(", ")}`);
|
|
160
|
+
}
|
|
161
|
+
// Normalize field names (snake_case → camelCase) before validation
|
|
162
|
+
const normalizedFields = requestedFields.map(normalizeFieldName);
|
|
163
|
+
const invalidFields = normalizedFields.filter((field) => !validFields.includes(field));
|
|
164
|
+
if (invalidFields.length > 0) {
|
|
165
|
+
const originalInvalid = requestedFields.filter((_, i) => !validFields.includes(normalizedFields[i]));
|
|
166
|
+
throw new Error(`Invalid fields for ${entityType}: ${originalInvalid.join(", ")}. ` +
|
|
167
|
+
`Valid fields: ${validFields.join(", ")} (also accepts snake_case: floor_id, room_id, etc.)`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Get default fields for an entity type
|
|
172
|
+
*/
|
|
173
|
+
export function getDefaultFields(entityType) {
|
|
174
|
+
const defaults = DEFAULT_FIELDS[entityType];
|
|
175
|
+
if (!defaults) {
|
|
176
|
+
throw new Error(`Unknown entity type: ${entityType}`);
|
|
177
|
+
}
|
|
178
|
+
return [...defaults];
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Validate and return fields (use defaults if none provided)
|
|
182
|
+
* Normalizes snake_case to camelCase for GraphQL queries
|
|
183
|
+
*/
|
|
184
|
+
export function getValidatedFields(entityType, requestedFields) {
|
|
185
|
+
if (!requestedFields || requestedFields.length === 0) {
|
|
186
|
+
return getDefaultFields(entityType);
|
|
187
|
+
}
|
|
188
|
+
validateFields(entityType, requestedFields);
|
|
189
|
+
// Normalize field names (snake_case → camelCase)
|
|
190
|
+
const normalizedFields = requestedFields.map(normalizeFieldName);
|
|
191
|
+
// Always include 'id' field (required by Apollo cache)
|
|
192
|
+
if (!normalizedFields.includes("id")) {
|
|
193
|
+
return ["id", ...normalizedFields];
|
|
194
|
+
}
|
|
195
|
+
return normalizedFields;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=field-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-validator.js","sourceRoot":"","sources":["../../src/utils/field-validator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fuzzy matching utilities for asset search
|
|
3
|
+
*/
|
|
4
|
+
export interface SearchableAsset {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
type: "site" | "building" | "floor" | "room" | "zone" | "sensor" | "hive";
|
|
8
|
+
[key: string]: unknown;
|
|
9
|
+
}
|
|
10
|
+
export interface MatchResult<T extends SearchableAsset> {
|
|
11
|
+
asset: T;
|
|
12
|
+
score: number;
|
|
13
|
+
matchedField: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Simple fuzzy matching - checks if query is contained in target (case-insensitive)
|
|
17
|
+
* Returns a score based on match quality
|
|
18
|
+
*/
|
|
19
|
+
export declare function fuzzyMatch(query: string, target: string): number;
|
|
20
|
+
/**
|
|
21
|
+
* Search through a list of assets by name
|
|
22
|
+
* Returns matches sorted by relevance score
|
|
23
|
+
*/
|
|
24
|
+
export declare function searchAssets<T extends SearchableAsset>(assets: T[], query: string, options?: {
|
|
25
|
+
matchFields?: string[];
|
|
26
|
+
minScore?: number;
|
|
27
|
+
maxResults?: number;
|
|
28
|
+
}): MatchResult<T>[];
|
|
29
|
+
//# sourceMappingURL=fuzzy-match.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fuzzy-match.d.ts","sourceRoot":"","sources":["../../src/utils/fuzzy-match.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;IAC1E,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,WAAW,CAAC,CAAC,SAAS,eAAe;IACpD,KAAK,EAAE,CAAC,CAAC;IACT,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA6BhE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,eAAe,EACpD,MAAM,EAAE,CAAC,EAAE,EACX,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACP,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CAChB,GACL,WAAW,CAAC,CAAC,CAAC,EAAE,CAsClB"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fuzzy matching utilities for asset search
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Simple fuzzy matching - checks if query is contained in target (case-insensitive)
|
|
6
|
+
* Returns a score based on match quality
|
|
7
|
+
*/
|
|
8
|
+
export function fuzzyMatch(query, target) {
|
|
9
|
+
const lowerQuery = query.toLowerCase().trim();
|
|
10
|
+
const lowerTarget = target.toLowerCase();
|
|
11
|
+
// Exact match
|
|
12
|
+
if (lowerTarget === lowerQuery) {
|
|
13
|
+
return 100;
|
|
14
|
+
}
|
|
15
|
+
// Starts with query
|
|
16
|
+
if (lowerTarget.startsWith(lowerQuery)) {
|
|
17
|
+
return 90;
|
|
18
|
+
}
|
|
19
|
+
// Word boundary match (e.g., "SF" matches "SF Tower") — check before generic contains
|
|
20
|
+
const words = lowerTarget.split(/\s+/);
|
|
21
|
+
for (const word of words) {
|
|
22
|
+
if (word.startsWith(lowerQuery)) {
|
|
23
|
+
return 80;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Contains query
|
|
27
|
+
if (lowerTarget.includes(lowerQuery)) {
|
|
28
|
+
return 70;
|
|
29
|
+
}
|
|
30
|
+
// No match
|
|
31
|
+
return 0;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Search through a list of assets by name
|
|
35
|
+
* Returns matches sorted by relevance score
|
|
36
|
+
*/
|
|
37
|
+
export function searchAssets(assets, query, options = {}) {
|
|
38
|
+
const { matchFields = ["name"], minScore = 70, maxResults = 20 } = options;
|
|
39
|
+
if (!query || query.trim().length === 0) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
// Score each asset
|
|
43
|
+
const scored = [];
|
|
44
|
+
for (const asset of assets) {
|
|
45
|
+
let bestScore = 0;
|
|
46
|
+
let bestField = "";
|
|
47
|
+
// Try matching against each field
|
|
48
|
+
for (const field of matchFields) {
|
|
49
|
+
const value = asset[field];
|
|
50
|
+
if (typeof value === "string") {
|
|
51
|
+
const score = fuzzyMatch(query, value);
|
|
52
|
+
if (score > bestScore) {
|
|
53
|
+
bestScore = score;
|
|
54
|
+
bestField = field;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Include if score meets threshold
|
|
59
|
+
if (bestScore >= minScore) {
|
|
60
|
+
scored.push({
|
|
61
|
+
asset,
|
|
62
|
+
score: bestScore,
|
|
63
|
+
matchedField: bestField,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// Sort by score (highest first) and limit results
|
|
68
|
+
return scored.sort((a, b) => b.score - a.score).slice(0, maxResults);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=fuzzy-match.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fuzzy-match.js","sourceRoot":"","sources":["../../src/utils/fuzzy-match.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,KAAa,EAAE,MAAc;IACtD,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,CAAC;IAC9C,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;IAEzC,cAAc;IACd,IAAI,WAAW,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,oBAAoB;IACpB,IAAI,WAAW,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACvC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,sFAAsF;IACtF,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACvC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IAED,iBAAiB;IACjB,IAAI,WAAW,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;QACrC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,WAAW;IACX,OAAO,CAAC,CAAC;AACX,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAW,EACX,KAAa,EACb,UAII,EAAE;IAEN,MAAM,EAAE,WAAW,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,EAAE,EAAE,UAAU,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAE3E,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,mBAAmB;IACnB,MAAM,MAAM,GAAqB,EAAE,CAAC;IAEpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,IAAI,SAAS,GAAG,EAAE,CAAC;QAEnB,kCAAkC;QAClC,KAAK,MAAM,KAAK,IAAI,WAAW,EAAE,CAAC;YAChC,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;gBAC9B,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;gBACvC,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;oBACtB,SAAS,GAAG,KAAK,CAAC;oBAClB,SAAS,GAAG,KAAK,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,mCAAmC;QACnC,IAAI,SAAS,IAAI,QAAQ,EAAE,CAAC;YAC1B,MAAM,CAAC,IAAI,CAAC;gBACV,KAAK;gBACL,KAAK,EAAE,SAAS;gBAChB,YAAY,EAAE,SAAS;aACxB,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,kDAAkD;IAClD,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC;AACvE,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared GraphQL error handling and device filtering utilities
|
|
3
|
+
*
|
|
4
|
+
* Eliminates repeated catch-block boilerplate and test-device filtering
|
|
5
|
+
* across tool implementations.
|
|
6
|
+
*/
|
|
7
|
+
import type { Sensor, Hive } from "../clients/types.js";
|
|
8
|
+
/**
|
|
9
|
+
* Re-throw as a formatted MCP error if the error is a GraphQL/network error.
|
|
10
|
+
* No-ops for non-GraphQL errors, allowing the caller to re-throw the original.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* catch (error: unknown) {
|
|
14
|
+
* rethrowIfGraphQLError(error);
|
|
15
|
+
* throw error;
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
export declare function rethrowIfGraphQLError(error: unknown): void;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a sensor is a production device (not a test/placeholder).
|
|
21
|
+
* Filters out mirror/virtual sensors (mi-rr-or*) and fake test sensors (fa-ke*).
|
|
22
|
+
*/
|
|
23
|
+
export declare function isProductionSensor(sensor: Sensor): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Check if a hive is a production device (not a test/placeholder).
|
|
26
|
+
* Filters out hives with fake serial numbers.
|
|
27
|
+
*/
|
|
28
|
+
export declare function isProductionHive(hive: Hive): boolean;
|
|
29
|
+
//# sourceMappingURL=graphql-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphql-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/graphql-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAGxD;;;;;;;;;GASG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI,CAK1D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAO1D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAMpD"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared GraphQL error handling and device filtering utilities
|
|
3
|
+
*
|
|
4
|
+
* Eliminates repeated catch-block boilerplate and test-device filtering
|
|
5
|
+
* across tool implementations.
|
|
6
|
+
*/
|
|
7
|
+
import { translateGraphQLError, formatMCPError } from "../errors/mcp-errors.js";
|
|
8
|
+
/**
|
|
9
|
+
* Re-throw as a formatted MCP error if the error is a GraphQL/network error.
|
|
10
|
+
* No-ops for non-GraphQL errors, allowing the caller to re-throw the original.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* catch (error: unknown) {
|
|
14
|
+
* rethrowIfGraphQLError(error);
|
|
15
|
+
* throw error;
|
|
16
|
+
* }
|
|
17
|
+
*/
|
|
18
|
+
export function rethrowIfGraphQLError(error) {
|
|
19
|
+
if (error && typeof error === "object" && ("graphQLErrors" in error || "networkError" in error)) {
|
|
20
|
+
const mcpError = translateGraphQLError(error);
|
|
21
|
+
throw new Error(formatMCPError(mcpError));
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Check if a sensor is a production device (not a test/placeholder).
|
|
26
|
+
* Filters out mirror/virtual sensors (mi-rr-or*) and fake test sensors (fa-ke*).
|
|
27
|
+
*/
|
|
28
|
+
export function isProductionSensor(sensor) {
|
|
29
|
+
return (!!sensor.mac_address &&
|
|
30
|
+
sensor.mac_address.trim() !== "" &&
|
|
31
|
+
!sensor.mac_address.startsWith("mi-rr-or") &&
|
|
32
|
+
!sensor.mac_address.startsWith("fa-ke"));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Check if a hive is a production device (not a test/placeholder).
|
|
36
|
+
* Filters out hives with fake serial numbers.
|
|
37
|
+
*/
|
|
38
|
+
export function isProductionHive(hive) {
|
|
39
|
+
return (!!hive.serialNumber &&
|
|
40
|
+
hive.serialNumber.trim() !== "" &&
|
|
41
|
+
!hive.serialNumber.toLowerCase().startsWith("fake"));
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=graphql-helpers.js.map
|