@adventurelabs/scout-core 1.4.84 → 1.4.86
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/api_keys/actions.d.ts +2 -1
- package/dist/api_keys/actions.js +2 -2
- package/dist/helpers/contacts.d.ts +10 -0
- package/dist/helpers/contacts.js +71 -0
- package/dist/helpers/document_templates.d.ts +7 -0
- package/dist/helpers/document_templates.js +63 -0
- package/dist/helpers/documents.d.ts +12 -0
- package/dist/helpers/documents.js +107 -0
- package/dist/helpers/herds.js +92 -13
- package/dist/helpers/index.d.ts +9 -1
- package/dist/helpers/index.js +9 -1
- package/dist/helpers/issuers.d.ts +7 -0
- package/dist/helpers/issuers.js +63 -0
- package/dist/helpers/layers.d.ts +3 -0
- package/dist/helpers/layers.js +20 -0
- package/dist/helpers/lifecycle.d.ts +2 -1
- package/dist/helpers/lifecycle.js +9 -0
- package/dist/helpers/localizations.d.ts +6 -0
- package/dist/helpers/localizations.js +51 -0
- package/dist/helpers/maintenance_requests.d.ts +15 -0
- package/dist/helpers/maintenance_requests.js +128 -0
- package/dist/helpers/manufacturers.d.ts +8 -0
- package/dist/helpers/manufacturers.js +52 -0
- package/dist/helpers/parts.d.ts +8 -1
- package/dist/helpers/parts.js +38 -0
- package/dist/helpers/plans.d.ts +3 -0
- package/dist/helpers/plans.js +20 -0
- package/dist/helpers/product_numbers.d.ts +7 -0
- package/dist/helpers/product_numbers.js +66 -0
- package/dist/helpers/products.d.ts +9 -0
- package/dist/helpers/products.js +65 -0
- package/dist/helpers/providers.d.ts +3 -0
- package/dist/helpers/providers.js +20 -0
- package/dist/helpers/users.d.ts +1 -0
- package/dist/helpers/users.js +30 -0
- package/dist/helpers/zones.d.ts +2 -1
- package/dist/helpers/zones.js +2 -2
- package/dist/hooks/useScoutRefresh.js +24 -8
- package/dist/index.d.ts +13 -3
- package/dist/index.js +11 -1
- package/dist/store/scout.d.ts +1 -0
- package/dist/store/scout.js +18 -2
- package/dist/types/db.d.ts +38 -4
- package/dist/types/herd_module.d.ts +2 -17
- package/dist/types/herd_module.js +0 -166
- package/dist/types/supabase.d.ts +686 -45
- package/dist/types/supabase.js +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IApiKeyScout } from "../types/db";
|
|
2
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
3
|
export declare function test_api_key_loading(device_id: number): Promise<boolean>;
|
|
3
4
|
export declare function server_list_api_keys(device_id: number): Promise<IApiKeyScout[]>;
|
|
4
|
-
export declare function server_list_api_keys_batch(device_ids: number[]): Promise<{
|
|
5
|
+
export declare function server_list_api_keys_batch(device_ids: number[], client?: SupabaseClient): Promise<{
|
|
5
6
|
[device_id: number]: IApiKeyScout[];
|
|
6
7
|
}>;
|
package/dist/api_keys/actions.js
CHANGED
|
@@ -31,8 +31,8 @@ export async function server_list_api_keys(device_id) {
|
|
|
31
31
|
}
|
|
32
32
|
return data_to_return;
|
|
33
33
|
}
|
|
34
|
-
export async function server_list_api_keys_batch(device_ids) {
|
|
35
|
-
const supabase = await newServerClient();
|
|
34
|
+
export async function server_list_api_keys_batch(device_ids, client) {
|
|
35
|
+
const supabase = client || (await newServerClient());
|
|
36
36
|
// Check if the batch function exists by trying a simple call
|
|
37
37
|
try {
|
|
38
38
|
const { data, error } = await supabase.rpc("load_api_keys_batch", {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Database } from "../types/supabase";
|
|
2
|
+
import { IContact, ContactInsert, ContactUpdate } from "../types/db";
|
|
3
|
+
import { IWebResponseCompatible } from "../types/requests";
|
|
4
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
5
|
+
export declare function get_contacts_by_herd_id(client: SupabaseClient<Database>, herd_id: number, options?: {
|
|
6
|
+
include_inactive?: boolean;
|
|
7
|
+
}): Promise<IWebResponseCompatible<IContact[]>>;
|
|
8
|
+
export declare function get_contact_by_id(client: SupabaseClient<Database>, contact_id: number): Promise<IWebResponseCompatible<IContact | null>>;
|
|
9
|
+
export declare function create_contact(client: SupabaseClient<Database>, row: ContactInsert): Promise<IWebResponseCompatible<IContact | null>>;
|
|
10
|
+
export declare function update_contact(client: SupabaseClient<Database>, contact_id: number, patch: ContactUpdate): Promise<IWebResponseCompatible<IContact | null>>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { IWebResponse } from "../types/requests";
|
|
2
|
+
export async function get_contacts_by_herd_id(client, herd_id, options) {
|
|
3
|
+
let query = client.from("contacts").select("*").eq("herd_id", herd_id);
|
|
4
|
+
if (!options?.include_inactive) {
|
|
5
|
+
query = query.eq("lifecycle", "active");
|
|
6
|
+
}
|
|
7
|
+
const { data, error } = await query.order("name");
|
|
8
|
+
if (error) {
|
|
9
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
10
|
+
}
|
|
11
|
+
return IWebResponse.success(data ?? []).to_compatible();
|
|
12
|
+
}
|
|
13
|
+
export async function get_contact_by_id(client, contact_id) {
|
|
14
|
+
const { data, error } = await client
|
|
15
|
+
.from("contacts")
|
|
16
|
+
.select("*")
|
|
17
|
+
.eq("id", contact_id)
|
|
18
|
+
.maybeSingle();
|
|
19
|
+
if (error) {
|
|
20
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
21
|
+
}
|
|
22
|
+
if (!data) {
|
|
23
|
+
return IWebResponse.error("Contact not found")
|
|
24
|
+
.to_compatible();
|
|
25
|
+
}
|
|
26
|
+
return IWebResponse.success(data).to_compatible();
|
|
27
|
+
}
|
|
28
|
+
export async function create_contact(client, row) {
|
|
29
|
+
if (row.herd_id == null) {
|
|
30
|
+
return IWebResponse.error("herd_id is required")
|
|
31
|
+
.to_compatible();
|
|
32
|
+
}
|
|
33
|
+
if (!row.name?.trim()) {
|
|
34
|
+
return IWebResponse.error("name is required")
|
|
35
|
+
.to_compatible();
|
|
36
|
+
}
|
|
37
|
+
const { data, error } = await client
|
|
38
|
+
.from("contacts")
|
|
39
|
+
.insert([row])
|
|
40
|
+
.select("*")
|
|
41
|
+
.single();
|
|
42
|
+
if (error) {
|
|
43
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
44
|
+
}
|
|
45
|
+
if (!data) {
|
|
46
|
+
return IWebResponse.error("Failed to create contact")
|
|
47
|
+
.to_compatible();
|
|
48
|
+
}
|
|
49
|
+
return IWebResponse.success(data).to_compatible();
|
|
50
|
+
}
|
|
51
|
+
export async function update_contact(client, contact_id, patch) {
|
|
52
|
+
const { id: _id, herd_id: _hid, created_at: _ca, ...updateData } = patch;
|
|
53
|
+
if (Object.keys(updateData).length === 0) {
|
|
54
|
+
return IWebResponse.error("No valid fields to update")
|
|
55
|
+
.to_compatible();
|
|
56
|
+
}
|
|
57
|
+
const { data, error } = await client
|
|
58
|
+
.from("contacts")
|
|
59
|
+
.update(updateData)
|
|
60
|
+
.eq("id", contact_id)
|
|
61
|
+
.select("*")
|
|
62
|
+
.single();
|
|
63
|
+
if (error) {
|
|
64
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
65
|
+
}
|
|
66
|
+
if (!data) {
|
|
67
|
+
return IWebResponse.error("Contact not found")
|
|
68
|
+
.to_compatible();
|
|
69
|
+
}
|
|
70
|
+
return IWebResponse.success(data).to_compatible();
|
|
71
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IDocumentTemplate, DocumentTemplateInsert, DocumentTemplateUpdate } from "../types/db";
|
|
2
|
+
import { IWebResponseCompatible } from "../types/requests";
|
|
3
|
+
export declare function server_get_document_templates(): Promise<IWebResponseCompatible<IDocumentTemplate[]>>;
|
|
4
|
+
export declare function server_get_document_template_by_id(template_id: number): Promise<IWebResponseCompatible<IDocumentTemplate | null>>;
|
|
5
|
+
export declare function server_get_document_templates_by_localization(localization_id: number): Promise<IWebResponseCompatible<IDocumentTemplate[]>>;
|
|
6
|
+
export declare function server_create_document_template(row: DocumentTemplateInsert): Promise<IWebResponseCompatible<IDocumentTemplate | null>>;
|
|
7
|
+
export declare function server_update_document_template(template_id: number, updates: DocumentTemplateUpdate): Promise<IWebResponseCompatible<IDocumentTemplate | null>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { newServerClient } from "../supabase/server";
|
|
3
|
+
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
+
export async function server_get_document_templates() {
|
|
5
|
+
const supabase = await newServerClient();
|
|
6
|
+
const { data, error } = await supabase
|
|
7
|
+
.from("document_templates")
|
|
8
|
+
.select("*")
|
|
9
|
+
.order("name");
|
|
10
|
+
if (error) {
|
|
11
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
|
|
12
|
+
}
|
|
13
|
+
return IWebResponse.success(data ?? []).to_compatible();
|
|
14
|
+
}
|
|
15
|
+
export async function server_get_document_template_by_id(template_id) {
|
|
16
|
+
const supabase = await newServerClient();
|
|
17
|
+
const { data, error } = await supabase
|
|
18
|
+
.from("document_templates")
|
|
19
|
+
.select("*")
|
|
20
|
+
.eq("id", template_id)
|
|
21
|
+
.maybeSingle();
|
|
22
|
+
if (error) {
|
|
23
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
24
|
+
}
|
|
25
|
+
return IWebResponse.success(data).to_compatible();
|
|
26
|
+
}
|
|
27
|
+
export async function server_get_document_templates_by_localization(localization_id) {
|
|
28
|
+
const supabase = await newServerClient();
|
|
29
|
+
const { data, error } = await supabase
|
|
30
|
+
.from("document_templates")
|
|
31
|
+
.select("*")
|
|
32
|
+
.eq("localization_id", localization_id)
|
|
33
|
+
.order("name");
|
|
34
|
+
if (error) {
|
|
35
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
|
|
36
|
+
}
|
|
37
|
+
return IWebResponse.success(data ?? []).to_compatible();
|
|
38
|
+
}
|
|
39
|
+
export async function server_create_document_template(row) {
|
|
40
|
+
const supabase = await newServerClient();
|
|
41
|
+
const { data, error } = await supabase
|
|
42
|
+
.from("document_templates")
|
|
43
|
+
.insert(row)
|
|
44
|
+
.select("*")
|
|
45
|
+
.single();
|
|
46
|
+
if (error) {
|
|
47
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
48
|
+
}
|
|
49
|
+
return IWebResponse.success(data).to_compatible();
|
|
50
|
+
}
|
|
51
|
+
export async function server_update_document_template(template_id, updates) {
|
|
52
|
+
const supabase = await newServerClient();
|
|
53
|
+
const { data, error } = await supabase
|
|
54
|
+
.from("document_templates")
|
|
55
|
+
.update(updates)
|
|
56
|
+
.eq("id", template_id)
|
|
57
|
+
.select("*")
|
|
58
|
+
.single();
|
|
59
|
+
if (error) {
|
|
60
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
61
|
+
}
|
|
62
|
+
return IWebResponse.success(data).to_compatible();
|
|
63
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Database } from "../types/supabase";
|
|
2
|
+
import { IDocument, DocumentInsert, DocumentUpdate } from "../types/db";
|
|
3
|
+
import { IWebResponseCompatible } from "../types/requests";
|
|
4
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
5
|
+
export declare function get_documents_by_herd_id(client: SupabaseClient<Database>, herd_id: number): Promise<IWebResponseCompatible<IDocument[]>>;
|
|
6
|
+
export declare function get_documents_by_device_id(client: SupabaseClient<Database>, device_id: number): Promise<IWebResponseCompatible<IDocument[]>>;
|
|
7
|
+
export declare function get_documents_by_user_id(client: SupabaseClient<Database>, user_id: string): Promise<IWebResponseCompatible<IDocument[]>>;
|
|
8
|
+
export declare function get_documents_by_product_id(client: SupabaseClient<Database>, product_id: number): Promise<IWebResponseCompatible<IDocument[]>>;
|
|
9
|
+
export declare function get_document_by_id(client: SupabaseClient<Database>, document_id: number): Promise<IWebResponseCompatible<IDocument | null>>;
|
|
10
|
+
export declare function create_document(client: SupabaseClient<Database>, row: DocumentInsert): Promise<IWebResponseCompatible<IDocument | null>>;
|
|
11
|
+
export declare function update_document(client: SupabaseClient<Database>, document_id: number, patch: DocumentUpdate): Promise<IWebResponseCompatible<IDocument | null>>;
|
|
12
|
+
export declare function delete_document(client: SupabaseClient<Database>, document_id: number): Promise<IWebResponseCompatible<IDocument | null>>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { IWebResponse } from "../types/requests";
|
|
2
|
+
function assert_document_insert(row) {
|
|
3
|
+
if (!row.uri?.trim()) {
|
|
4
|
+
return IWebResponse.error("uri is required")
|
|
5
|
+
.to_compatible();
|
|
6
|
+
}
|
|
7
|
+
const owners = [row.user_id, row.herd_id, row.device_id, row.product_id];
|
|
8
|
+
const owner_count = owners.filter((owner) => owner != null).length;
|
|
9
|
+
if (owner_count !== 1) {
|
|
10
|
+
return IWebResponse.error("exactly one of user_id, herd_id, device_id, or product_id is required").to_compatible();
|
|
11
|
+
}
|
|
12
|
+
return null;
|
|
13
|
+
}
|
|
14
|
+
async function get_documents_by(client, column, value) {
|
|
15
|
+
const { data, error } = await client
|
|
16
|
+
.from("documents")
|
|
17
|
+
.select("*")
|
|
18
|
+
.eq(column, value)
|
|
19
|
+
.order("created_at", { ascending: false });
|
|
20
|
+
if (error) {
|
|
21
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
22
|
+
}
|
|
23
|
+
return IWebResponse.success(data ?? []).to_compatible();
|
|
24
|
+
}
|
|
25
|
+
export async function get_documents_by_herd_id(client, herd_id) {
|
|
26
|
+
return get_documents_by(client, "herd_id", herd_id);
|
|
27
|
+
}
|
|
28
|
+
export async function get_documents_by_device_id(client, device_id) {
|
|
29
|
+
return get_documents_by(client, "device_id", device_id);
|
|
30
|
+
}
|
|
31
|
+
export async function get_documents_by_user_id(client, user_id) {
|
|
32
|
+
return get_documents_by(client, "user_id", user_id);
|
|
33
|
+
}
|
|
34
|
+
export async function get_documents_by_product_id(client, product_id) {
|
|
35
|
+
return get_documents_by(client, "product_id", product_id);
|
|
36
|
+
}
|
|
37
|
+
export async function get_document_by_id(client, document_id) {
|
|
38
|
+
const { data, error } = await client
|
|
39
|
+
.from("documents")
|
|
40
|
+
.select("*")
|
|
41
|
+
.eq("id", document_id)
|
|
42
|
+
.maybeSingle();
|
|
43
|
+
if (error) {
|
|
44
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
45
|
+
}
|
|
46
|
+
if (!data) {
|
|
47
|
+
return IWebResponse.error("Document not found")
|
|
48
|
+
.to_compatible();
|
|
49
|
+
}
|
|
50
|
+
return IWebResponse.success(data).to_compatible();
|
|
51
|
+
}
|
|
52
|
+
export async function create_document(client, row) {
|
|
53
|
+
const invalid = assert_document_insert(row);
|
|
54
|
+
if (invalid) {
|
|
55
|
+
return invalid;
|
|
56
|
+
}
|
|
57
|
+
const { data, error } = await client
|
|
58
|
+
.from("documents")
|
|
59
|
+
.insert([row])
|
|
60
|
+
.select("*")
|
|
61
|
+
.single();
|
|
62
|
+
if (error) {
|
|
63
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
64
|
+
}
|
|
65
|
+
if (!data) {
|
|
66
|
+
return IWebResponse.error("Failed to create document")
|
|
67
|
+
.to_compatible();
|
|
68
|
+
}
|
|
69
|
+
return IWebResponse.success(data).to_compatible();
|
|
70
|
+
}
|
|
71
|
+
export async function update_document(client, document_id, patch) {
|
|
72
|
+
const { id: _id, created_at: _ca, created_by: _cb, ...updateData } = patch;
|
|
73
|
+
if (Object.keys(updateData).length === 0) {
|
|
74
|
+
return IWebResponse.error("No valid fields to update")
|
|
75
|
+
.to_compatible();
|
|
76
|
+
}
|
|
77
|
+
const { data, error } = await client
|
|
78
|
+
.from("documents")
|
|
79
|
+
.update(updateData)
|
|
80
|
+
.eq("id", document_id)
|
|
81
|
+
.select("*")
|
|
82
|
+
.single();
|
|
83
|
+
if (error) {
|
|
84
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
85
|
+
}
|
|
86
|
+
if (!data) {
|
|
87
|
+
return IWebResponse.error("Document not found")
|
|
88
|
+
.to_compatible();
|
|
89
|
+
}
|
|
90
|
+
return IWebResponse.success(data).to_compatible();
|
|
91
|
+
}
|
|
92
|
+
export async function delete_document(client, document_id) {
|
|
93
|
+
const { data, error } = await client
|
|
94
|
+
.from("documents")
|
|
95
|
+
.delete()
|
|
96
|
+
.eq("id", document_id)
|
|
97
|
+
.select("*")
|
|
98
|
+
.single();
|
|
99
|
+
if (error) {
|
|
100
|
+
return IWebResponse.error(error.message).to_compatible();
|
|
101
|
+
}
|
|
102
|
+
if (!data) {
|
|
103
|
+
return IWebResponse.error("Document not found")
|
|
104
|
+
.to_compatible();
|
|
105
|
+
}
|
|
106
|
+
return IWebResponse.success(data).to_compatible();
|
|
107
|
+
}
|
package/dist/helpers/herds.js
CHANGED
|
@@ -1,7 +1,18 @@
|
|
|
1
1
|
"use server";
|
|
2
|
+
import { createHash } from "crypto";
|
|
2
3
|
import { newServerClient } from "../supabase/server";
|
|
3
4
|
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
-
import {
|
|
5
|
+
import { LABELS } from "../constants/annotator";
|
|
6
|
+
import { get_devices_by_herd } from "./devices";
|
|
7
|
+
import { server_get_plans_by_herd_ids } from "./plans";
|
|
8
|
+
import { server_get_layers_by_herd_ids } from "./layers";
|
|
9
|
+
import { server_get_providers_by_herd_ids } from "./providers";
|
|
10
|
+
import { server_get_users_with_herd_access_batch } from "./users";
|
|
11
|
+
import { get_parts_by_herd_ids } from "./parts";
|
|
12
|
+
import { server_get_more_zones_and_actions_for_herd } from "./zones";
|
|
13
|
+
import { server_list_api_keys_batch } from "../api_keys/actions";
|
|
14
|
+
import { server_get_session_summaries_by_herd } from "./session_summaries";
|
|
15
|
+
import { server_get_session_usage_over_time_by_herd } from "./sessions";
|
|
5
16
|
export async function get_herds(client) {
|
|
6
17
|
const { data: herds } = await client.from("herds").select();
|
|
7
18
|
if (!herds) {
|
|
@@ -71,12 +82,17 @@ export async function createHerd(newHerd) {
|
|
|
71
82
|
return IWebResponse.success(true).to_compatible();
|
|
72
83
|
}
|
|
73
84
|
}
|
|
85
|
+
// Stable hash of modules (queries return rows in a deterministic DB order), minus
|
|
86
|
+
// the per-fetch timestamp, so the client can skip no-op updates without a deep walk.
|
|
87
|
+
function hashHerdModules(modules) {
|
|
88
|
+
const stable = modules.map(({ timestamp_last_refreshed: _ts, ...rest }) => rest);
|
|
89
|
+
return createHash("sha1").update(JSON.stringify(stable)).digest("hex");
|
|
90
|
+
}
|
|
74
91
|
export async function server_load_herd_modules() {
|
|
75
92
|
const startTime = Date.now();
|
|
76
|
-
const
|
|
77
|
-
const herdsResult = await get_herds_with_location(
|
|
78
|
-
if (herdsResult.status !== EnumWebResponse.SUCCESS ||
|
|
79
|
-
!herdsResult.data) {
|
|
93
|
+
const client = await newServerClient();
|
|
94
|
+
const herdsResult = await get_herds_with_location(client);
|
|
95
|
+
if (herdsResult.status !== EnumWebResponse.SUCCESS || !herdsResult.data) {
|
|
80
96
|
return {
|
|
81
97
|
status: EnumWebResponse.ERROR,
|
|
82
98
|
msg: herdsResult.msg ?? "Failed to load herds",
|
|
@@ -84,26 +100,88 @@ export async function server_load_herd_modules() {
|
|
|
84
100
|
time_finished: Date.now(),
|
|
85
101
|
time_sent: Date.now(),
|
|
86
102
|
server_processing_time_ms: Date.now() - startTime,
|
|
103
|
+
content_hash: "",
|
|
87
104
|
};
|
|
88
105
|
}
|
|
89
106
|
const herds = herdsResult.data.filter((h) => h.id != null);
|
|
90
|
-
const endTime = Date.now();
|
|
91
|
-
const totalLoadTime = endTime - startTime;
|
|
92
107
|
if (herds.length === 0) {
|
|
93
|
-
|
|
108
|
+
const endTime = Date.now();
|
|
109
|
+
console.log(`[server_load_herd_modules] No accessible herds (${endTime - startTime}ms)`);
|
|
94
110
|
return {
|
|
95
111
|
status: EnumWebResponse.SUCCESS,
|
|
96
112
|
msg: "No herds accessible",
|
|
97
113
|
data: [],
|
|
98
114
|
time_finished: endTime,
|
|
99
115
|
time_sent: endTime,
|
|
100
|
-
server_processing_time_ms:
|
|
116
|
+
server_processing_time_ms: endTime - startTime,
|
|
117
|
+
content_hash: hashHerdModules([]),
|
|
101
118
|
};
|
|
102
119
|
}
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
const
|
|
106
|
-
|
|
120
|
+
const herdIds = herds.map((h) => h.id);
|
|
121
|
+
// Run a per-herd RPC across all herds in parallel, tolerating individual failures.
|
|
122
|
+
const perHerd = (fn) => Promise.all(herds.map((h) => fn(h.id).catch(() => ({
|
|
123
|
+
status: EnumWebResponse.ERROR,
|
|
124
|
+
msg: "",
|
|
125
|
+
data: null,
|
|
126
|
+
}))));
|
|
127
|
+
const grouped = (p) => p.then((r) => r.data ?? {}).catch(() => ({}));
|
|
128
|
+
const [plansByHerd, layersByHerd, providersByHerd, usersByHerd, partsByDevice, devicesResults, zonesResults, summariesResults, usageResults,] = await Promise.all([
|
|
129
|
+
grouped(server_get_plans_by_herd_ids(herdIds, client)),
|
|
130
|
+
grouped(server_get_layers_by_herd_ids(herdIds, client)),
|
|
131
|
+
grouped(server_get_providers_by_herd_ids(herdIds, client)),
|
|
132
|
+
server_get_users_with_herd_access_batch(herdIds, client)
|
|
133
|
+
.then((r) => (r.status === EnumWebResponse.SUCCESS ? r.data : null))
|
|
134
|
+
.catch(() => null),
|
|
135
|
+
grouped(get_parts_by_herd_ids(client, herdIds)),
|
|
136
|
+
perHerd((id) => get_devices_by_herd(id, client)),
|
|
137
|
+
perHerd((id) => server_get_more_zones_and_actions_for_herd(id, 0, 10, client)),
|
|
138
|
+
perHerd((id) => server_get_session_summaries_by_herd(id, client)),
|
|
139
|
+
perHerd((id) => server_get_session_usage_over_time_by_herd(id, client)),
|
|
140
|
+
]);
|
|
141
|
+
const devicesByHerdIndex = devicesResults.map((res) => res.status === EnumWebResponse.SUCCESS && res.data ? res.data : []);
|
|
142
|
+
const allDevices = devicesByHerdIndex.flat();
|
|
143
|
+
const allDeviceIds = allDevices.map((device) => device.id ?? 0);
|
|
144
|
+
let apiKeysByDevice = {};
|
|
145
|
+
if (allDeviceIds.length > 0) {
|
|
146
|
+
try {
|
|
147
|
+
apiKeysByDevice = await server_list_api_keys_batch(allDeviceIds, client);
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
console.error(`[server_load_herd_modules] Failed to load API keys:`, error);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
for (const device of allDevices) {
|
|
154
|
+
const deviceId = device.id ?? 0;
|
|
155
|
+
device.api_keys_scout = apiKeysByDevice[deviceId] || [];
|
|
156
|
+
device.parts = partsByDevice[deviceId] || [];
|
|
157
|
+
}
|
|
158
|
+
const serialized_herd_modules = herds.map((herd, index) => {
|
|
159
|
+
const zonesRes = zonesResults[index];
|
|
160
|
+
const summariesRes = summariesResults[index];
|
|
161
|
+
const usageRes = usageResults[index];
|
|
162
|
+
return {
|
|
163
|
+
herd,
|
|
164
|
+
devices: devicesByHerdIndex[index],
|
|
165
|
+
timestamp_last_refreshed: Date.now(),
|
|
166
|
+
user_roles: usersByHerd ? usersByHerd[herd.id] ?? [] : null,
|
|
167
|
+
labels: LABELS,
|
|
168
|
+
plans: plansByHerd[herd.id] ?? [],
|
|
169
|
+
zones: zonesRes.status === EnumWebResponse.SUCCESS && zonesRes.data
|
|
170
|
+
? zonesRes.data
|
|
171
|
+
: [],
|
|
172
|
+
layers: layersByHerd[herd.id] ?? [],
|
|
173
|
+
providers: providersByHerd[herd.id] ?? [],
|
|
174
|
+
session_summaries: summariesRes.status === EnumWebResponse.SUCCESS && summariesRes.data
|
|
175
|
+
? summariesRes.data
|
|
176
|
+
: null,
|
|
177
|
+
session_usage: usageRes.status === EnumWebResponse.SUCCESS && usageRes.data
|
|
178
|
+
? usageRes.data
|
|
179
|
+
: null,
|
|
180
|
+
};
|
|
181
|
+
});
|
|
182
|
+
const endTime = Date.now();
|
|
183
|
+
const totalLoadTime = endTime - startTime;
|
|
184
|
+
console.log(`[server_load_herd_modules] Loaded ${herds.length} herds in ${totalLoadTime}ms (batched queries)`);
|
|
107
185
|
return {
|
|
108
186
|
status: EnumWebResponse.SUCCESS,
|
|
109
187
|
msg: "Herd modules loaded successfully",
|
|
@@ -111,5 +189,6 @@ export async function server_load_herd_modules() {
|
|
|
111
189
|
time_finished: endTime,
|
|
112
190
|
time_sent: endTime,
|
|
113
191
|
server_processing_time_ms: totalLoadTime,
|
|
192
|
+
content_hash: hashHerdModules(serialized_herd_modules),
|
|
114
193
|
};
|
|
115
194
|
}
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export * from "./auth";
|
|
|
3
3
|
export * from "./bounding_boxes";
|
|
4
4
|
export * from "./chat";
|
|
5
5
|
export * from "./certificates";
|
|
6
|
-
export * from "./credentials";
|
|
7
6
|
export * from "./user_credentials";
|
|
8
7
|
export * from "./herd_credentials";
|
|
9
8
|
export * from "./db";
|
|
@@ -17,6 +16,15 @@ export * from "./herds";
|
|
|
17
16
|
export * from "./location";
|
|
18
17
|
export * from "./lifecycle";
|
|
19
18
|
export * from "./models";
|
|
19
|
+
export * from "./manufacturers";
|
|
20
|
+
export * from "./products";
|
|
21
|
+
export * from "./product_numbers";
|
|
22
|
+
export * from "./localizations";
|
|
23
|
+
export * from "./issuers";
|
|
24
|
+
export * from "./document_templates";
|
|
25
|
+
export * from "./documents";
|
|
26
|
+
export * from "./maintenance_requests";
|
|
27
|
+
export * from "./contacts";
|
|
20
28
|
export * from "./plans";
|
|
21
29
|
export * from "./sessions";
|
|
22
30
|
export * from "./segmentations_sam3";
|
package/dist/helpers/index.js
CHANGED
|
@@ -3,7 +3,6 @@ export * from "./auth";
|
|
|
3
3
|
export * from "./bounding_boxes";
|
|
4
4
|
export * from "./chat";
|
|
5
5
|
export * from "./certificates";
|
|
6
|
-
export * from "./credentials";
|
|
7
6
|
export * from "./user_credentials";
|
|
8
7
|
export * from "./herd_credentials";
|
|
9
8
|
export * from "./db";
|
|
@@ -17,6 +16,15 @@ export * from "./herds";
|
|
|
17
16
|
export * from "./location";
|
|
18
17
|
export * from "./lifecycle";
|
|
19
18
|
export * from "./models";
|
|
19
|
+
export * from "./manufacturers";
|
|
20
|
+
export * from "./products";
|
|
21
|
+
export * from "./product_numbers";
|
|
22
|
+
export * from "./localizations";
|
|
23
|
+
export * from "./issuers";
|
|
24
|
+
export * from "./document_templates";
|
|
25
|
+
export * from "./documents";
|
|
26
|
+
export * from "./maintenance_requests";
|
|
27
|
+
export * from "./contacts";
|
|
20
28
|
export * from "./plans";
|
|
21
29
|
export * from "./sessions";
|
|
22
30
|
export * from "./segmentations_sam3";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { IIssuer, IssuerInsert, IssuerUpdate } from "../types/db";
|
|
2
|
+
import { IWebResponseCompatible } from "../types/requests";
|
|
3
|
+
export declare function server_get_issuers(): Promise<IWebResponseCompatible<IIssuer[]>>;
|
|
4
|
+
export declare function server_get_issuer_by_id(issuer_id: number): Promise<IWebResponseCompatible<IIssuer | null>>;
|
|
5
|
+
export declare function server_get_issuers_by_localization(localization_id: number): Promise<IWebResponseCompatible<IIssuer[]>>;
|
|
6
|
+
export declare function server_create_issuer(row: IssuerInsert): Promise<IWebResponseCompatible<IIssuer | null>>;
|
|
7
|
+
export declare function server_update_issuer(issuer_id: number, updates: IssuerUpdate): Promise<IWebResponseCompatible<IIssuer | null>>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use server";
|
|
2
|
+
import { newServerClient } from "../supabase/server";
|
|
3
|
+
import { EnumWebResponse, IWebResponse, } from "../types/requests";
|
|
4
|
+
export async function server_get_issuers() {
|
|
5
|
+
const supabase = await newServerClient();
|
|
6
|
+
const { data, error } = await supabase
|
|
7
|
+
.from("issuers")
|
|
8
|
+
.select("*")
|
|
9
|
+
.order("name");
|
|
10
|
+
if (error) {
|
|
11
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
|
|
12
|
+
}
|
|
13
|
+
return IWebResponse.success(data ?? []).to_compatible();
|
|
14
|
+
}
|
|
15
|
+
export async function server_get_issuer_by_id(issuer_id) {
|
|
16
|
+
const supabase = await newServerClient();
|
|
17
|
+
const { data, error } = await supabase
|
|
18
|
+
.from("issuers")
|
|
19
|
+
.select("*")
|
|
20
|
+
.eq("id", issuer_id)
|
|
21
|
+
.maybeSingle();
|
|
22
|
+
if (error) {
|
|
23
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
24
|
+
}
|
|
25
|
+
return IWebResponse.success(data).to_compatible();
|
|
26
|
+
}
|
|
27
|
+
export async function server_get_issuers_by_localization(localization_id) {
|
|
28
|
+
const supabase = await newServerClient();
|
|
29
|
+
const { data, error } = await supabase
|
|
30
|
+
.from("issuers")
|
|
31
|
+
.select("*")
|
|
32
|
+
.eq("localization_id", localization_id)
|
|
33
|
+
.order("name");
|
|
34
|
+
if (error) {
|
|
35
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
|
|
36
|
+
}
|
|
37
|
+
return IWebResponse.success(data ?? []).to_compatible();
|
|
38
|
+
}
|
|
39
|
+
export async function server_create_issuer(row) {
|
|
40
|
+
const supabase = await newServerClient();
|
|
41
|
+
const { data, error } = await supabase
|
|
42
|
+
.from("issuers")
|
|
43
|
+
.insert(row)
|
|
44
|
+
.select("*")
|
|
45
|
+
.single();
|
|
46
|
+
if (error) {
|
|
47
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
48
|
+
}
|
|
49
|
+
return IWebResponse.success(data).to_compatible();
|
|
50
|
+
}
|
|
51
|
+
export async function server_update_issuer(issuer_id, updates) {
|
|
52
|
+
const supabase = await newServerClient();
|
|
53
|
+
const { data, error } = await supabase
|
|
54
|
+
.from("issuers")
|
|
55
|
+
.update(updates)
|
|
56
|
+
.eq("id", issuer_id)
|
|
57
|
+
.select("*")
|
|
58
|
+
.single();
|
|
59
|
+
if (error) {
|
|
60
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
61
|
+
}
|
|
62
|
+
return IWebResponse.success(data).to_compatible();
|
|
63
|
+
}
|
package/dist/helpers/layers.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { Database } from "../types/supabase";
|
|
1
2
|
import { ILayer } from "../types/db";
|
|
2
3
|
import { IWebResponseCompatible } from "../types/requests";
|
|
4
|
+
import { SupabaseClient } from "@supabase/supabase-js";
|
|
3
5
|
export declare function server_get_layers_by_herd(herd_id: number): Promise<IWebResponseCompatible<ILayer[]>>;
|
|
6
|
+
export declare function server_get_layers_by_herd_ids(herd_ids: number[], client: SupabaseClient<Database>): Promise<IWebResponseCompatible<Record<number, ILayer[]>>>;
|
package/dist/helpers/layers.js
CHANGED
|
@@ -19,3 +19,23 @@ export async function server_get_layers_by_herd(herd_id) {
|
|
|
19
19
|
return IWebResponse.success(data).to_compatible();
|
|
20
20
|
}
|
|
21
21
|
}
|
|
22
|
+
// Fetches layers for many herds in one query, grouped by herd_id.
|
|
23
|
+
export async function server_get_layers_by_herd_ids(herd_ids, client) {
|
|
24
|
+
var _a;
|
|
25
|
+
if (herd_ids.length === 0) {
|
|
26
|
+
return IWebResponse.success({}).to_compatible();
|
|
27
|
+
}
|
|
28
|
+
const { data, error } = await client
|
|
29
|
+
.from("layers")
|
|
30
|
+
.select("*")
|
|
31
|
+
.in("herd_id", herd_ids)
|
|
32
|
+
.order("id", { ascending: true });
|
|
33
|
+
if (error) {
|
|
34
|
+
return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
|
|
35
|
+
}
|
|
36
|
+
const grouped = {};
|
|
37
|
+
for (const row of data ?? []) {
|
|
38
|
+
(grouped[_a = row.herd_id] ?? (grouped[_a] = [])).push(row);
|
|
39
|
+
}
|
|
40
|
+
return IWebResponse.success(grouped).to_compatible();
|
|
41
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SupabaseClient } from "@supabase/supabase-js";
|
|
2
2
|
import { Database } from "../types/supabase";
|
|
3
|
-
import { EntityLifecycle, IArtifact, IDeviceRow, IEvent, IHerdAllowedDomain, IPart, ISession, IUserProfileRow, IUserRolePerHerd } from "../types/db";
|
|
3
|
+
import { EntityLifecycle, IArtifact, IContact, IDeviceRow, IEvent, IHerdAllowedDomain, IPart, ISession, IUserProfileRow, IUserRolePerHerd } from "../types/db";
|
|
4
4
|
import { IWebResponseCompatible } from "../types/requests";
|
|
5
5
|
export interface LifecycleUpdateOptions {
|
|
6
6
|
lifecycle_reason?: string | null;
|
|
@@ -15,4 +15,5 @@ export declare function update_part_lifecycle(client: SupabaseClient<Database>,
|
|
|
15
15
|
export declare function update_event_lifecycle(client: SupabaseClient<Database>, event_id: number, lifecycle: EntityLifecycle, options?: LifecycleUpdateOptions): Promise<IWebResponseCompatible<IEvent | null>>;
|
|
16
16
|
export declare function update_artifact_lifecycle(client: SupabaseClient<Database>, artifact_id: number, lifecycle: EntityLifecycle, options?: LifecycleUpdateOptions): Promise<IWebResponseCompatible<IArtifact | null>>;
|
|
17
17
|
export declare function update_user_role_per_herd_lifecycle(client: SupabaseClient<Database>, membership_id: number, lifecycle: EntityLifecycle, options?: LifecycleUpdateOptions): Promise<IWebResponseCompatible<IUserRolePerHerd | null>>;
|
|
18
|
+
export declare function update_contact_lifecycle(client: SupabaseClient<Database>, contact_id: number, lifecycle: EntityLifecycle, options?: LifecycleUpdateOptions): Promise<IWebResponseCompatible<IContact | null>>;
|
|
18
19
|
export declare function update_herd_allowed_domain_lifecycle(client: SupabaseClient<Database>, domain_id: number, lifecycle: EntityLifecycle, options?: LifecycleUpdateOptions): Promise<IWebResponseCompatible<IHerdAllowedDomain | null>>;
|
|
@@ -83,6 +83,15 @@ export async function update_user_role_per_herd_lifecycle(client, membership_id,
|
|
|
83
83
|
.single();
|
|
84
84
|
return lifecycle_result(data, error, "Herd membership not found or lifecycle update failed");
|
|
85
85
|
}
|
|
86
|
+
export async function update_contact_lifecycle(client, contact_id, lifecycle, options) {
|
|
87
|
+
const { data, error } = await client
|
|
88
|
+
.from("contacts")
|
|
89
|
+
.update(build_lifecycle_patch(lifecycle, options))
|
|
90
|
+
.eq("id", contact_id)
|
|
91
|
+
.select("*")
|
|
92
|
+
.single();
|
|
93
|
+
return lifecycle_result(data, error, "Contact not found or lifecycle update failed");
|
|
94
|
+
}
|
|
86
95
|
export async function update_herd_allowed_domain_lifecycle(client, domain_id, lifecycle, options) {
|
|
87
96
|
const { data, error } = await client
|
|
88
97
|
.from("herd_allowed_domains")
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { ILocalization, LocalizationInsert, LocalizationUpdate } from "../types/db";
|
|
2
|
+
import { IWebResponseCompatible } from "../types/requests";
|
|
3
|
+
export declare function server_get_localizations(): Promise<IWebResponseCompatible<ILocalization[]>>;
|
|
4
|
+
export declare function server_get_localization_by_id(localization_id: number): Promise<IWebResponseCompatible<ILocalization | null>>;
|
|
5
|
+
export declare function server_create_localization(row: LocalizationInsert): Promise<IWebResponseCompatible<ILocalization | null>>;
|
|
6
|
+
export declare function server_update_localization(localization_id: number, updates: LocalizationUpdate): Promise<IWebResponseCompatible<ILocalization | null>>;
|