@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.
Files changed (48) hide show
  1. package/dist/api_keys/actions.d.ts +2 -1
  2. package/dist/api_keys/actions.js +2 -2
  3. package/dist/helpers/contacts.d.ts +10 -0
  4. package/dist/helpers/contacts.js +71 -0
  5. package/dist/helpers/document_templates.d.ts +7 -0
  6. package/dist/helpers/document_templates.js +63 -0
  7. package/dist/helpers/documents.d.ts +12 -0
  8. package/dist/helpers/documents.js +107 -0
  9. package/dist/helpers/herds.js +92 -13
  10. package/dist/helpers/index.d.ts +9 -1
  11. package/dist/helpers/index.js +9 -1
  12. package/dist/helpers/issuers.d.ts +7 -0
  13. package/dist/helpers/issuers.js +63 -0
  14. package/dist/helpers/layers.d.ts +3 -0
  15. package/dist/helpers/layers.js +20 -0
  16. package/dist/helpers/lifecycle.d.ts +2 -1
  17. package/dist/helpers/lifecycle.js +9 -0
  18. package/dist/helpers/localizations.d.ts +6 -0
  19. package/dist/helpers/localizations.js +51 -0
  20. package/dist/helpers/maintenance_requests.d.ts +15 -0
  21. package/dist/helpers/maintenance_requests.js +128 -0
  22. package/dist/helpers/manufacturers.d.ts +8 -0
  23. package/dist/helpers/manufacturers.js +52 -0
  24. package/dist/helpers/parts.d.ts +8 -1
  25. package/dist/helpers/parts.js +38 -0
  26. package/dist/helpers/plans.d.ts +3 -0
  27. package/dist/helpers/plans.js +20 -0
  28. package/dist/helpers/product_numbers.d.ts +7 -0
  29. package/dist/helpers/product_numbers.js +66 -0
  30. package/dist/helpers/products.d.ts +9 -0
  31. package/dist/helpers/products.js +65 -0
  32. package/dist/helpers/providers.d.ts +3 -0
  33. package/dist/helpers/providers.js +20 -0
  34. package/dist/helpers/users.d.ts +1 -0
  35. package/dist/helpers/users.js +30 -0
  36. package/dist/helpers/zones.d.ts +2 -1
  37. package/dist/helpers/zones.js +2 -2
  38. package/dist/hooks/useScoutRefresh.js +24 -8
  39. package/dist/index.d.ts +13 -3
  40. package/dist/index.js +11 -1
  41. package/dist/store/scout.d.ts +1 -0
  42. package/dist/store/scout.js +18 -2
  43. package/dist/types/db.d.ts +38 -4
  44. package/dist/types/herd_module.d.ts +2 -17
  45. package/dist/types/herd_module.js +0 -166
  46. package/dist/types/supabase.d.ts +686 -45
  47. package/dist/types/supabase.js +1 -0
  48. package/package.json +1 -1
@@ -0,0 +1,51 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
+ export async function server_get_localizations() {
5
+ const supabase = await newServerClient();
6
+ const { data, error } = await supabase
7
+ .from("localizations")
8
+ .select("*")
9
+ .order("region");
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_localization_by_id(localization_id) {
16
+ const supabase = await newServerClient();
17
+ const { data, error } = await supabase
18
+ .from("localizations")
19
+ .select("*")
20
+ .eq("id", localization_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_create_localization(row) {
28
+ const supabase = await newServerClient();
29
+ const { data, error } = await supabase
30
+ .from("localizations")
31
+ .insert(row)
32
+ .select("*")
33
+ .single();
34
+ if (error) {
35
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
36
+ }
37
+ return IWebResponse.success(data).to_compatible();
38
+ }
39
+ export async function server_update_localization(localization_id, updates) {
40
+ const supabase = await newServerClient();
41
+ const { data, error } = await supabase
42
+ .from("localizations")
43
+ .update(updates)
44
+ .eq("id", localization_id)
45
+ .select("*")
46
+ .single();
47
+ if (error) {
48
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
49
+ }
50
+ return IWebResponse.success(data).to_compatible();
51
+ }
@@ -0,0 +1,15 @@
1
+ import { Database } from "../types/supabase";
2
+ import { IMaintenanceRequest, MaintenanceRequestInsert, MaintenanceRequestUpdate } from "../types/db";
3
+ import { IWebResponseCompatible } from "../types/requests";
4
+ import { SupabaseClient } from "@supabase/supabase-js";
5
+ export declare function get_maintenance_requests_by_device_id(client: SupabaseClient<Database>, device_id: number): Promise<IWebResponseCompatible<IMaintenanceRequest[]>>;
6
+ export declare function get_maintenance_requests_by_part_id(client: SupabaseClient<Database>, part_id: number): Promise<IWebResponseCompatible<IMaintenanceRequest[]>>;
7
+ export declare function get_maintenance_requests_by_herd_id(client: SupabaseClient<Database>, herd_id: number, options?: {
8
+ limit?: number;
9
+ offset?: number;
10
+ }): Promise<IWebResponseCompatible<IMaintenanceRequest[]>>;
11
+ export declare function get_maintenance_requests_count_by_herd_id(client: SupabaseClient<Database>, herd_id: number): Promise<IWebResponseCompatible<number>>;
12
+ export declare function get_maintenance_request_by_id(client: SupabaseClient<Database>, request_id: number): Promise<IWebResponseCompatible<IMaintenanceRequest | null>>;
13
+ export declare function create_maintenance_request(client: SupabaseClient<Database>, row: MaintenanceRequestInsert): Promise<IWebResponseCompatible<IMaintenanceRequest | null>>;
14
+ export declare function update_maintenance_request(client: SupabaseClient<Database>, request_id: number, patch: MaintenanceRequestUpdate): Promise<IWebResponseCompatible<IMaintenanceRequest | null>>;
15
+ export declare function delete_maintenance_request(client: SupabaseClient<Database>, request_id: number): Promise<IWebResponseCompatible<IMaintenanceRequest | null>>;
@@ -0,0 +1,128 @@
1
+ import { IWebResponse } from "../types/requests";
2
+ function assert_maintenance_request_insert(row) {
3
+ if (!row.description?.trim()) {
4
+ return IWebResponse.error("description is required").to_compatible();
5
+ }
6
+ if (!row.defect_timestamp) {
7
+ return IWebResponse.error("defect_timestamp is required").to_compatible();
8
+ }
9
+ const targets = [row.device_id, row.part_id];
10
+ const target_count = targets.filter((target) => target != null).length;
11
+ if (target_count !== 1) {
12
+ return IWebResponse.error("exactly one of device_id or part_id is required").to_compatible();
13
+ }
14
+ return null;
15
+ }
16
+ export async function get_maintenance_requests_by_device_id(client, device_id) {
17
+ const { data, error } = await client
18
+ .from("maintenance_requests")
19
+ .select("*")
20
+ .eq("device_id", device_id)
21
+ .order("created_at", { ascending: false });
22
+ if (error) {
23
+ return IWebResponse.error(error.message)
24
+ .to_compatible();
25
+ }
26
+ return IWebResponse.success(data ?? []).to_compatible();
27
+ }
28
+ export async function get_maintenance_requests_by_part_id(client, part_id) {
29
+ const { data, error } = await client
30
+ .from("maintenance_requests")
31
+ .select("*")
32
+ .eq("part_id", part_id)
33
+ .order("created_at", { ascending: false });
34
+ if (error) {
35
+ return IWebResponse.error(error.message)
36
+ .to_compatible();
37
+ }
38
+ return IWebResponse.success(data ?? []).to_compatible();
39
+ }
40
+ export async function get_maintenance_requests_by_herd_id(client, herd_id, options) {
41
+ const { data, error } = await client.rpc("get_maintenance_requests_for_herd", {
42
+ herd_id_caller: herd_id,
43
+ limit_caller: options?.limit ?? 50,
44
+ offset_caller: options?.offset ?? 0,
45
+ });
46
+ if (error) {
47
+ return IWebResponse.error(error.message)
48
+ .to_compatible();
49
+ }
50
+ return IWebResponse.success(data ?? []).to_compatible();
51
+ }
52
+ export async function get_maintenance_requests_count_by_herd_id(client, herd_id) {
53
+ const { data, error } = await client.rpc("get_total_maintenance_requests_for_herd", { herd_id_caller: herd_id });
54
+ if (error) {
55
+ return IWebResponse.error(error.message).to_compatible();
56
+ }
57
+ return IWebResponse.success(data ?? 0).to_compatible();
58
+ }
59
+ export async function get_maintenance_request_by_id(client, request_id) {
60
+ const { data, error } = await client
61
+ .from("maintenance_requests")
62
+ .select("*")
63
+ .eq("id", request_id)
64
+ .maybeSingle();
65
+ if (error) {
66
+ return IWebResponse.error(error.message)
67
+ .to_compatible();
68
+ }
69
+ if (!data) {
70
+ return IWebResponse.error("Maintenance request not found").to_compatible();
71
+ }
72
+ return IWebResponse.success(data).to_compatible();
73
+ }
74
+ export async function create_maintenance_request(client, row) {
75
+ const invalid = assert_maintenance_request_insert(row);
76
+ if (invalid) {
77
+ return invalid;
78
+ }
79
+ const { data, error } = await client
80
+ .from("maintenance_requests")
81
+ .insert([row])
82
+ .select("*")
83
+ .single();
84
+ if (error) {
85
+ return IWebResponse.error(error.message)
86
+ .to_compatible();
87
+ }
88
+ if (!data) {
89
+ return IWebResponse.error("Failed to create maintenance request").to_compatible();
90
+ }
91
+ return IWebResponse.success(data).to_compatible();
92
+ }
93
+ export async function update_maintenance_request(client, request_id, patch) {
94
+ const { id: _id, created_at: _ca, ...updateData } = patch;
95
+ if (Object.keys(updateData).length === 0) {
96
+ return IWebResponse.error("No valid fields to update").to_compatible();
97
+ }
98
+ const { data, error } = await client
99
+ .from("maintenance_requests")
100
+ .update(updateData)
101
+ .eq("id", request_id)
102
+ .select("*")
103
+ .single();
104
+ if (error) {
105
+ return IWebResponse.error(error.message)
106
+ .to_compatible();
107
+ }
108
+ if (!data) {
109
+ return IWebResponse.error("Maintenance request not found").to_compatible();
110
+ }
111
+ return IWebResponse.success(data).to_compatible();
112
+ }
113
+ export async function delete_maintenance_request(client, request_id) {
114
+ const { data, error } = await client
115
+ .from("maintenance_requests")
116
+ .delete()
117
+ .eq("id", request_id)
118
+ .select("*")
119
+ .single();
120
+ if (error) {
121
+ return IWebResponse.error(error.message)
122
+ .to_compatible();
123
+ }
124
+ if (!data) {
125
+ return IWebResponse.error("Maintenance request not found").to_compatible();
126
+ }
127
+ return IWebResponse.success(data).to_compatible();
128
+ }
@@ -0,0 +1,8 @@
1
+ import { IManufacturer, ManufacturerInsert, ManufacturerUpdate } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ export declare function server_get_manufacturers(options?: {
4
+ include_inactive?: boolean;
5
+ }): Promise<IWebResponseCompatible<IManufacturer[]>>;
6
+ export declare function server_get_manufacturer_by_id(manufacturer_id: number): Promise<IWebResponseCompatible<IManufacturer | null>>;
7
+ export declare function server_create_manufacturer(row: ManufacturerInsert): Promise<IWebResponseCompatible<IManufacturer | null>>;
8
+ export declare function server_update_manufacturer(manufacturer_id: number, updates: ManufacturerUpdate): Promise<IWebResponseCompatible<IManufacturer | null>>;
@@ -0,0 +1,52 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
+ export async function server_get_manufacturers(options) {
5
+ const supabase = await newServerClient();
6
+ let query = supabase.from("manufacturers").select("*").order("name");
7
+ if (!options?.include_inactive) {
8
+ query = query.eq("lifecycle", "active");
9
+ }
10
+ const { data, error } = await query;
11
+ if (error) {
12
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
13
+ }
14
+ return IWebResponse.success(data ?? []).to_compatible();
15
+ }
16
+ export async function server_get_manufacturer_by_id(manufacturer_id) {
17
+ const supabase = await newServerClient();
18
+ const { data, error } = await supabase
19
+ .from("manufacturers")
20
+ .select("*")
21
+ .eq("id", manufacturer_id)
22
+ .maybeSingle();
23
+ if (error) {
24
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
25
+ }
26
+ return IWebResponse.success(data).to_compatible();
27
+ }
28
+ export async function server_create_manufacturer(row) {
29
+ const supabase = await newServerClient();
30
+ const { data, error } = await supabase
31
+ .from("manufacturers")
32
+ .insert(row)
33
+ .select("*")
34
+ .single();
35
+ if (error) {
36
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
37
+ }
38
+ return IWebResponse.success(data).to_compatible();
39
+ }
40
+ export async function server_update_manufacturer(manufacturer_id, updates) {
41
+ const supabase = await newServerClient();
42
+ const { data, error } = await supabase
43
+ .from("manufacturers")
44
+ .update(updates)
45
+ .eq("id", manufacturer_id)
46
+ .select("*")
47
+ .single();
48
+ if (error) {
49
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
50
+ }
51
+ return IWebResponse.success(data).to_compatible();
52
+ }
@@ -1,5 +1,5 @@
1
1
  import { Database } from "../types/supabase";
2
- import { EntityLifecycle, IPart, PartInsert } from "../types/db";
2
+ import { EntityLifecycle, IPart, IPartWithProduct, PartInsert } from "../types/db";
3
3
  import { IWebResponseCompatible } from "../types/requests";
4
4
  import { SupabaseClient } from "@supabase/supabase-js";
5
5
  import { LifecycleUpdateOptions } from "./lifecycle";
@@ -75,6 +75,13 @@ export declare function get_parts_by_certificate_id(client: SupabaseClient<Datab
75
75
  * @param herd_id - ID of the herd to get parts for
76
76
  */
77
77
  export declare function get_parts_by_herd_id(client: SupabaseClient<Database>, herd_id: number): Promise<IWebResponseCompatible<IPart[]>>;
78
+ /**
79
+ * Retrieves active parts for all devices across many herds in one query,
80
+ * grouped by device_id.
81
+ * @param client - Supabase client instance
82
+ * @param herd_ids - IDs of the herds to get parts for
83
+ */
84
+ export declare function get_parts_by_herd_ids(client: SupabaseClient<Database>, herd_ids: number[]): Promise<IWebResponseCompatible<Record<number, IPartWithProduct[]>>>;
78
85
  /**
79
86
  * Restores a deleted part to active lifecycle
80
87
  * @param client - Supabase client instance
@@ -238,6 +238,44 @@ export async function get_parts_by_herd_id(client, herd_id) {
238
238
  }
239
239
  return IWebResponse.success(data).to_compatible();
240
240
  }
241
+ /**
242
+ * Retrieves active parts for all devices across many herds in one query,
243
+ * grouped by device_id.
244
+ * @param client - Supabase client instance
245
+ * @param herd_ids - IDs of the herds to get parts for
246
+ */
247
+ export async function get_parts_by_herd_ids(client, herd_ids) {
248
+ var _a;
249
+ if (herd_ids.length === 0) {
250
+ return IWebResponse.success({}).to_compatible();
251
+ }
252
+ const { data, error } = await client
253
+ .from("parts")
254
+ .select(`
255
+ *,
256
+ devices!parts_device_id_fkey(herd_id),
257
+ product_numbers!parts_product_number_fkey(products(*))
258
+ `)
259
+ .in("devices.herd_id", herd_ids)
260
+ .eq("lifecycle", "active")
261
+ .order("created_at", { ascending: false })
262
+ .order("id", { ascending: true });
263
+ if (error) {
264
+ return IWebResponse.error(error.message).to_compatible();
265
+ }
266
+ const grouped = {};
267
+ for (const row of data ?? []) {
268
+ if (row.device_id == null)
269
+ continue;
270
+ const { product_numbers, devices: _devices, ...partRow } = row;
271
+ const part = {
272
+ ...partRow,
273
+ product: product_numbers?.products ?? null,
274
+ };
275
+ (grouped[_a = row.device_id] ?? (grouped[_a] = [])).push(part);
276
+ }
277
+ return IWebResponse.success(grouped).to_compatible();
278
+ }
241
279
  /**
242
280
  * Restores a deleted part to active lifecycle
243
281
  * @param client - Supabase client instance
@@ -1,5 +1,8 @@
1
+ import { Database } from "../types/supabase";
1
2
  import { IPlan } from "../types/db";
2
3
  import { IWebResponseCompatible } from "../types/requests";
4
+ import { SupabaseClient } from "@supabase/supabase-js";
3
5
  export declare function server_get_plans_by_herd(herd_id: number): Promise<IWebResponseCompatible<IPlan[]>>;
6
+ export declare function server_get_plans_by_herd_ids(herd_ids: number[], client: SupabaseClient<Database>): Promise<IWebResponseCompatible<Record<number, IPlan[]>>>;
4
7
  export declare function server_create_plans(plans: IPlan[]): Promise<IWebResponseCompatible<IPlan[]>>;
5
8
  export declare function server_delete_plans_by_ids(plan_ids: number[]): Promise<IWebResponseCompatible<boolean>>;
@@ -19,6 +19,26 @@ export async function server_get_plans_by_herd(herd_id) {
19
19
  return IWebResponse.success(data).to_compatible();
20
20
  }
21
21
  }
22
+ // Fetches plans for many herds in one query, grouped by herd_id.
23
+ export async function server_get_plans_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("plans")
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
+ }
22
42
  // function that uploads plan to our db
23
43
  export async function server_create_plans(plans) {
24
44
  // loop through plans and format
@@ -0,0 +1,7 @@
1
+ import { IProduct, IProductNumber, ProductNumberInsert, ProductNumberUpdate } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ export declare function server_get_product_numbers_by_product(product_id: number): Promise<IWebResponseCompatible<IProductNumber[]>>;
4
+ export declare function server_get_product_number(product_number: string): Promise<IWebResponseCompatible<IProductNumber | null>>;
5
+ export declare function server_get_product_for_product_number(product_number: string): Promise<IWebResponseCompatible<IProduct | null>>;
6
+ export declare function server_create_product_number(row: ProductNumberInsert): Promise<IWebResponseCompatible<IProductNumber | null>>;
7
+ export declare function server_update_product_number(product_number: string, updates: ProductNumberUpdate): Promise<IWebResponseCompatible<IProductNumber | null>>;
@@ -0,0 +1,66 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
+ export async function server_get_product_numbers_by_product(product_id) {
5
+ const supabase = await newServerClient();
6
+ const { data, error } = await supabase
7
+ .from("product_numbers")
8
+ .select("*")
9
+ .eq("product_id", product_id)
10
+ .order("product_number");
11
+ if (error) {
12
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
13
+ }
14
+ return IWebResponse.success(data ?? []).to_compatible();
15
+ }
16
+ export async function server_get_product_number(product_number) {
17
+ const supabase = await newServerClient();
18
+ const { data, error } = await supabase
19
+ .from("product_numbers")
20
+ .select("*")
21
+ .eq("product_number", product_number)
22
+ .maybeSingle();
23
+ if (error) {
24
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
25
+ }
26
+ return IWebResponse.success(data).to_compatible();
27
+ }
28
+ // Resolves the product line for a given product_number via the FK chain.
29
+ export async function server_get_product_for_product_number(product_number) {
30
+ const supabase = await newServerClient();
31
+ const { data, error } = await supabase
32
+ .from("product_numbers")
33
+ .select("products(*)")
34
+ .eq("product_number", product_number)
35
+ .maybeSingle();
36
+ if (error) {
37
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
38
+ }
39
+ const product = data?.products ?? null;
40
+ return IWebResponse.success(product).to_compatible();
41
+ }
42
+ export async function server_create_product_number(row) {
43
+ const supabase = await newServerClient();
44
+ const { data, error } = await supabase
45
+ .from("product_numbers")
46
+ .insert(row)
47
+ .select("*")
48
+ .single();
49
+ if (error) {
50
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
51
+ }
52
+ return IWebResponse.success(data).to_compatible();
53
+ }
54
+ export async function server_update_product_number(product_number, updates) {
55
+ const supabase = await newServerClient();
56
+ const { data, error } = await supabase
57
+ .from("product_numbers")
58
+ .update(updates)
59
+ .eq("product_number", product_number)
60
+ .select("*")
61
+ .single();
62
+ if (error) {
63
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
64
+ }
65
+ return IWebResponse.success(data).to_compatible();
66
+ }
@@ -0,0 +1,9 @@
1
+ import { IProduct, ProductInsert, ProductUpdate } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ export declare function server_get_products(options?: {
4
+ include_inactive?: boolean;
5
+ }): Promise<IWebResponseCompatible<IProduct[]>>;
6
+ export declare function server_get_product_by_id(product_id: number): Promise<IWebResponseCompatible<IProduct | null>>;
7
+ export declare function server_get_products_by_manufacturer(manufacturer_id: number): Promise<IWebResponseCompatible<IProduct[]>>;
8
+ export declare function server_create_product(row: ProductInsert): Promise<IWebResponseCompatible<IProduct | null>>;
9
+ export declare function server_update_product(product_id: number, updates: ProductUpdate): Promise<IWebResponseCompatible<IProduct | null>>;
@@ -0,0 +1,65 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
+ export async function server_get_products(options) {
5
+ const supabase = await newServerClient();
6
+ let query = supabase.from("products").select("*").order("name");
7
+ if (!options?.include_inactive) {
8
+ query = query.eq("lifecycle", "active");
9
+ }
10
+ const { data, error } = await query;
11
+ if (error) {
12
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
13
+ }
14
+ return IWebResponse.success(data ?? []).to_compatible();
15
+ }
16
+ export async function server_get_product_by_id(product_id) {
17
+ const supabase = await newServerClient();
18
+ const { data, error } = await supabase
19
+ .from("products")
20
+ .select("*")
21
+ .eq("id", product_id)
22
+ .maybeSingle();
23
+ if (error) {
24
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
25
+ }
26
+ return IWebResponse.success(data).to_compatible();
27
+ }
28
+ export async function server_get_products_by_manufacturer(manufacturer_id) {
29
+ const supabase = await newServerClient();
30
+ const { data, error } = await supabase
31
+ .from("products")
32
+ .select("*")
33
+ .eq("manufacturer_id", manufacturer_id)
34
+ .eq("lifecycle", "active")
35
+ .order("name");
36
+ if (error) {
37
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: [] };
38
+ }
39
+ return IWebResponse.success(data ?? []).to_compatible();
40
+ }
41
+ export async function server_create_product(row) {
42
+ const supabase = await newServerClient();
43
+ const { data, error } = await supabase
44
+ .from("products")
45
+ .insert(row)
46
+ .select("*")
47
+ .single();
48
+ if (error) {
49
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
50
+ }
51
+ return IWebResponse.success(data).to_compatible();
52
+ }
53
+ export async function server_update_product(product_id, updates) {
54
+ const supabase = await newServerClient();
55
+ const { data, error } = await supabase
56
+ .from("products")
57
+ .update(updates)
58
+ .eq("id", product_id)
59
+ .select("*")
60
+ .single();
61
+ if (error) {
62
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
63
+ }
64
+ return IWebResponse.success(data).to_compatible();
65
+ }
@@ -1,6 +1,9 @@
1
+ import { Database } from "../types/supabase";
1
2
  import { IProvider } from "../types/db";
2
3
  import { IWebResponseCompatible } from "../types/requests";
4
+ import { SupabaseClient } from "@supabase/supabase-js";
3
5
  export declare function server_get_providers_by_herd(herd_id: number): Promise<IWebResponseCompatible<IProvider[]>>;
6
+ export declare function server_get_providers_by_herd_ids(herd_ids: number[], client: SupabaseClient<Database>): Promise<IWebResponseCompatible<Record<number, IProvider[]>>>;
4
7
  export declare function server_create_provider(provider: Omit<IProvider, "id" | "created_at">): Promise<IWebResponseCompatible<IProvider>>;
5
8
  export declare function server_update_provider(provider_id: number, updates: Partial<Omit<IProvider, "id" | "created_at">>): Promise<IWebResponseCompatible<IProvider>>;
6
9
  export declare function server_delete_providers_by_ids(provider_ids: number[]): Promise<IWebResponseCompatible<boolean>>;
@@ -19,6 +19,26 @@ export async function server_get_providers_by_herd(herd_id) {
19
19
  return IWebResponse.success(data).to_compatible();
20
20
  }
21
21
  }
22
+ // Fetches providers for many herds in one query, grouped by herd_id.
23
+ export async function server_get_providers_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("providers")
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
+ }
22
42
  // function that creates a new provider in our db
23
43
  export async function server_create_provider(provider) {
24
44
  const supabase = await newServerClient();
@@ -5,6 +5,7 @@ import { Database } from "../types/supabase";
5
5
  export declare function server_get_user_roles(herd_id: number): Promise<IWebResponseCompatible<IUserRolePerHerd[]>>;
6
6
  export declare function server_get_user(): Promise<IWebResponseCompatible<IUser | null>>;
7
7
  export declare function server_get_users_with_herd_access(herd_id: number, supabaseClient?: SupabaseClient): Promise<IWebResponseCompatible<IUserAndRole[]>>;
8
+ export declare function server_get_users_with_herd_access_batch(herd_ids: number[], client: SupabaseClient): Promise<IWebResponseCompatible<Record<number, IUserAndRole[]>>>;
8
9
  export declare function server_upsert_user_herd_role(herd_id: number, username: string, herd_role_id: number): Promise<IWebResponseCompatible<IUserAndRole | null>>;
9
10
  export type UserProfileUpdate = Database["public"]["Tables"]["users"]["Update"];
10
11
  export declare function update_user_profile(client: SupabaseClient<Database>, user_id: string, patch: UserProfileUpdate): Promise<IWebResponseCompatible<IUserProfileRow | null>>;
@@ -49,6 +49,36 @@ export async function server_get_users_with_herd_access(herd_id, supabaseClient)
49
49
  }));
50
50
  return IWebResponse.success(transformedData).to_compatible();
51
51
  }
52
+ // Fetches users-with-role for many herds in one query, grouped by herd_id.
53
+ export async function server_get_users_with_herd_access_batch(herd_ids, client) {
54
+ var _a;
55
+ if (herd_ids.length === 0) {
56
+ return IWebResponse.success({}).to_compatible();
57
+ }
58
+ const { data, error } = await client
59
+ .from("users_roles_per_herd")
60
+ .select(`
61
+ herd_id,
62
+ herd_role_id,
63
+ herd_roles (*),
64
+ users!users_roles_per_herd_user_id_fkey (*)
65
+ `)
66
+ .in("herd_id", herd_ids)
67
+ .order("herd_id", { ascending: true })
68
+ .order("user_id", { ascending: true });
69
+ if (error) {
70
+ return { status: EnumWebResponse.ERROR, msg: error.message, data: null };
71
+ }
72
+ const grouped = {};
73
+ for (const item of (data ?? [])) {
74
+ (grouped[_a = item.herd_id] ?? (grouped[_a] = [])).push({
75
+ user: item.users,
76
+ herd_role_id: item.herd_role_id,
77
+ herd_role: item.herd_roles,
78
+ });
79
+ }
80
+ return IWebResponse.success(grouped).to_compatible();
81
+ }
52
82
  export async function server_upsert_user_herd_role(herd_id, username, herd_role_id) {
53
83
  const supabase = await newServerClient();
54
84
  const { data: user, error: user_error } = await supabase
@@ -1,5 +1,6 @@
1
1
  import { IZoneWithActions } from "../types/db";
2
2
  import { IWebResponseCompatible } from "../types/requests";
3
+ import { SupabaseClient } from "@supabase/supabase-js";
3
4
  /**
4
5
  * Get more zones and actions for a herd
5
6
  * @param herd_id - The ID of the herd to get zones and actions for
@@ -8,7 +9,7 @@ import { IWebResponseCompatible } from "../types/requests";
8
9
  * @returns A list of zones and actions
9
10
  * @throws An error if the zones or actions are not fetched
10
11
  */
11
- export declare function server_get_more_zones_and_actions_for_herd(herd_id: number, offset: number, page_count?: number): Promise<IWebResponseCompatible<IZoneWithActions[]>>;
12
+ export declare function server_get_more_zones_and_actions_for_herd(herd_id: number, offset: number, page_count?: number, client?: SupabaseClient): Promise<IWebResponseCompatible<IZoneWithActions[]>>;
12
13
  /**
13
14
  * Create zones and actions for a herd
14
15
  * @param zones - The zones to create
@@ -8,10 +8,10 @@ import { EnumWebResponse, IWebResponse, } from "../types/requests";
8
8
  * @returns A list of zones and actions
9
9
  * @throws An error if the zones or actions are not fetched
10
10
  */
11
- export async function server_get_more_zones_and_actions_for_herd(herd_id, offset, page_count = 10) {
11
+ export async function server_get_more_zones_and_actions_for_herd(herd_id, offset, page_count = 10, client) {
12
12
  const from = offset * page_count;
13
13
  const to = from + page_count - 1;
14
- const supabase = await newServerClient();
14
+ const supabase = client || (await newServerClient());
15
15
  // make rpc call to get_events_with_tags_for_herd(herd_id, offset, limit)
16
16
  const { data, error } = await supabase.rpc("get_zones_and_actions_for_herd", {
17
17
  herd_id_caller: herd_id,