@adventurelabs/scout-core 1.0.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.
Files changed (90) hide show
  1. package/README.md +90 -0
  2. package/dist/api_keys/actions.d.ts +2 -0
  3. package/dist/api_keys/actions.js +20 -0
  4. package/dist/api_keys/index.d.ts +1 -0
  5. package/dist/api_keys/index.js +1 -0
  6. package/dist/constants/annotator.d.ts +1 -0
  7. package/dist/constants/annotator.js +11 -0
  8. package/dist/constants/app.d.ts +2 -0
  9. package/dist/constants/app.js +2 -0
  10. package/dist/constants/index.d.ts +2 -0
  11. package/dist/constants/index.js +2 -0
  12. package/dist/helpers/auth.d.ts +1 -0
  13. package/dist/helpers/auth.js +8 -0
  14. package/dist/helpers/bounding_boxes.d.ts +5 -0
  15. package/dist/helpers/bounding_boxes.js +43 -0
  16. package/dist/helpers/db.d.ts +3 -0
  17. package/dist/helpers/db.js +22 -0
  18. package/dist/helpers/devices.d.ts +8 -0
  19. package/dist/helpers/devices.js +92 -0
  20. package/dist/helpers/email.d.ts +7 -0
  21. package/dist/helpers/email.js +22 -0
  22. package/dist/helpers/events.d.ts +6 -0
  23. package/dist/helpers/events.js +71 -0
  24. package/dist/helpers/finance.d.ts +9 -0
  25. package/dist/helpers/finance.js +16 -0
  26. package/dist/helpers/gps.d.ts +5 -0
  27. package/dist/helpers/gps.js +11 -0
  28. package/dist/helpers/herds.d.ts +9 -0
  29. package/dist/helpers/herds.js +80 -0
  30. package/dist/helpers/index.d.ts +17 -0
  31. package/dist/helpers/index.js +17 -0
  32. package/dist/helpers/location.d.ts +1 -0
  33. package/dist/helpers/location.js +3 -0
  34. package/dist/helpers/plans.d.ts +5 -0
  35. package/dist/helpers/plans.js +61 -0
  36. package/dist/helpers/tags.d.ts +7 -0
  37. package/dist/helpers/tags.js +158 -0
  38. package/dist/helpers/time.d.ts +3 -0
  39. package/dist/helpers/time.js +11 -0
  40. package/dist/helpers/ui.d.ts +4 -0
  41. package/dist/helpers/ui.js +12 -0
  42. package/dist/helpers/users.d.ts +6 -0
  43. package/dist/helpers/users.js +66 -0
  44. package/dist/helpers/web.d.ts +1 -0
  45. package/dist/helpers/web.js +7 -0
  46. package/dist/helpers/zones.d.ts +18 -0
  47. package/dist/helpers/zones.js +108 -0
  48. package/dist/hooks/index.d.ts +2 -0
  49. package/dist/hooks/index.js +2 -0
  50. package/dist/hooks/useScoutDbListener.d.ts +1 -0
  51. package/dist/hooks/useScoutDbListener.js +94 -0
  52. package/dist/hooks/useScoutRefresh.d.ts +7 -0
  53. package/dist/hooks/useScoutRefresh.js +45 -0
  54. package/dist/index.d.ts +38 -0
  55. package/dist/index.js +43 -0
  56. package/dist/providers/ScoutRefreshProvider.d.ts +1 -0
  57. package/dist/providers/ScoutRefreshProvider.js +8 -0
  58. package/dist/providers/index.d.ts +1 -0
  59. package/dist/providers/index.js +1 -0
  60. package/dist/store/hooks.d.ts +1 -0
  61. package/dist/store/hooks.js +3 -0
  62. package/dist/store/index.d.ts +1 -0
  63. package/dist/store/index.js +1 -0
  64. package/dist/store/scout.d.ts +103 -0
  65. package/dist/store/scout.js +196 -0
  66. package/dist/supabase/client.d.ts +1 -0
  67. package/dist/supabase/client.js +5 -0
  68. package/dist/supabase/index.d.ts +3 -0
  69. package/dist/supabase/index.js +3 -0
  70. package/dist/supabase/middleware.d.ts +2 -0
  71. package/dist/supabase/middleware.js +46 -0
  72. package/dist/supabase/server.d.ts +636 -0
  73. package/dist/supabase/server.js +22 -0
  74. package/dist/types/bounding_boxes.d.ts +27 -0
  75. package/dist/types/bounding_boxes.js +11 -0
  76. package/dist/types/db.d.ts +42 -0
  77. package/dist/types/db.js +15 -0
  78. package/dist/types/gps.d.ts +21 -0
  79. package/dist/types/gps.js +13 -0
  80. package/dist/types/herd_module.d.ts +31 -0
  81. package/dist/types/herd_module.js +82 -0
  82. package/dist/types/index.d.ts +6 -0
  83. package/dist/types/index.js +6 -0
  84. package/dist/types/requests.d.ts +18 -0
  85. package/dist/types/requests.js +25 -0
  86. package/dist/types/supabase.d.ts +754 -0
  87. package/dist/types/supabase.js +25 -0
  88. package/dist/types/ui.d.ts +7 -0
  89. package/dist/types/ui.js +8 -0
  90. package/package.json +52 -0
package/README.md ADDED
@@ -0,0 +1,90 @@
1
+ # @adventurelabs/scout-core
2
+
3
+ Core utilities and helpers for Adventure Labs Scout applications.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @adventurelabs/scout-core
9
+ # or
10
+ yarn add @adventurelabs/scout-core
11
+ ```
12
+
13
+ ## Usage
14
+
15
+ ```typescript
16
+ import {
17
+ HerdModule,
18
+ IDevice,
19
+ IEvent,
20
+ isEmailValidForLogin,
21
+ useScoutDbListener,
22
+ useScoutRefresh,
23
+ } from "@adventurelabs/scout-core";
24
+
25
+ // Use the HerdModule class
26
+ const herdModule = new HerdModule(herd, devices, events, Date.now());
27
+
28
+ // Use helper functions
29
+ const isValidEmail = isEmailValidForLogin("user@adventurelabs.earth");
30
+
31
+ // Use React hooks for real-time database listening
32
+ useScoutDbListener(); // Automatically listens for changes to plans, devices, and tags
33
+
34
+ // Use refresh hook
35
+ const { handleRefresh } = useScoutRefresh({ autoRefresh: true });
36
+ ```
37
+
38
+ ## Available Modules
39
+
40
+ ### Types
41
+
42
+ - Database types from Supabase
43
+ - Herd, Device, Event, User interfaces
44
+ - Request/Response types
45
+
46
+ ### Helpers
47
+
48
+ - Authentication utilities
49
+ - Database operations
50
+ - Email validation
51
+ - GPS and location helpers
52
+ - Device and event management
53
+ - Tag and annotation utilities
54
+
55
+ ### Hooks
56
+
57
+ - `useScoutDbListener` - Real-time database listening for plans, devices, and tags
58
+ - `useScoutRefresh` - Data refresh utilities
59
+
60
+ ### Store
61
+
62
+ - Zustand-based state management for Scout applications
63
+
64
+ ### Supabase
65
+
66
+ - Client, server, and middleware utilities for Supabase integration
67
+
68
+ ### API Keys
69
+
70
+ - API key management utilities
71
+
72
+ ## Development
73
+
74
+ ```bash
75
+ # Install dependencies
76
+ yarn install
77
+
78
+ # Build the package
79
+ yarn build
80
+
81
+ # Watch for changes
82
+ yarn dev
83
+
84
+ # Clean build artifacts
85
+ yarn clean
86
+ ```
87
+
88
+ ## License
89
+
90
+ MIT
@@ -0,0 +1,2 @@
1
+ import { IApiKeyScout } from "../types/db";
2
+ export declare function server_list_api_keys(device_id: string): Promise<IApiKeyScout[]>;
@@ -0,0 +1,20 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ export async function server_list_api_keys(device_id) {
4
+ const supabase = await newServerClient();
5
+ const { data, error } = await supabase.rpc("load_api_keys", {
6
+ id_of_device: device_id,
7
+ });
8
+ if (error) {
9
+ console.error("Error listing API keys:", error.message);
10
+ }
11
+ if (!data)
12
+ return [];
13
+ const data_to_return = [];
14
+ for (let i = 0; i < data.length; i++) {
15
+ // convert data to IApiKeyScout
16
+ const converted_data = JSON.parse(data[i]);
17
+ data_to_return.push(converted_data);
18
+ }
19
+ return data_to_return;
20
+ }
@@ -0,0 +1 @@
1
+ export * from "./actions";
@@ -0,0 +1 @@
1
+ export * from "./actions";
@@ -0,0 +1 @@
1
+ export declare const LABELS: string[];
@@ -0,0 +1,11 @@
1
+ export const LABELS = [
2
+ "boar",
3
+ "human",
4
+ "vehicle",
5
+ "deer",
6
+ "giraffe",
7
+ "gorilla",
8
+ "lion",
9
+ "penguin",
10
+ "undefined",
11
+ ];
@@ -0,0 +1,2 @@
1
+ export declare const MAX_ITEMS_PER_PAGE_EVENTS = 24;
2
+ export declare const VALID_VIEWS: string[];
@@ -0,0 +1,2 @@
1
+ export const MAX_ITEMS_PER_PAGE_EVENTS = 24;
2
+ export const VALID_VIEWS = ["overview", "events", "security"];
@@ -0,0 +1,2 @@
1
+ export * from "./annotator";
2
+ export * from "./app";
@@ -0,0 +1,2 @@
1
+ export * from "./annotator";
2
+ export * from "./app";
@@ -0,0 +1 @@
1
+ export declare function isEmailValidForLogin(email: string, approved_domains?: string[]): boolean;
@@ -0,0 +1,8 @@
1
+ import { validateEmail } from "./email";
2
+ const APPROVED_DOMAINS = ["adventurelabs.earth", "conservaition.ai"];
3
+ export function isEmailValidForLogin(email, approved_domains = APPROVED_DOMAINS) {
4
+ return (validateEmail(email) && isEmailFromApprovedDomain(email, approved_domains));
5
+ }
6
+ function isEmailFromApprovedDomain(email, approved_domains = APPROVED_DOMAINS) {
7
+ return approved_domains.filter((domain) => email.endsWith(domain)).length > 0;
8
+ }
@@ -0,0 +1,5 @@
1
+ import { BoundingBox, EnumSourceBoundingBox } from "../types/bounding_boxes";
2
+ import { Tag } from "../types/db";
3
+ export declare function convertManualBoundingBoxToTag(boundingBox: BoundingBox, event_id: number): Tag;
4
+ export declare function convertTagToBoundingBox(tag: Tag, source: EnumSourceBoundingBox): BoundingBox;
5
+ export declare function formatBoundingBoxLabel(label: string): string;
@@ -0,0 +1,43 @@
1
+ import { SelectionStatus, } from "../types/bounding_boxes";
2
+ export function convertManualBoundingBoxToTag(boundingBox, event_id) {
3
+ const newClassName = boundingBox.label;
4
+ // try to convert if nan, make it 0
5
+ let newId = Number(boundingBox.id);
6
+ if (isNaN(newId)) {
7
+ newId = 0;
8
+ }
9
+ const newTag = {
10
+ id: newId,
11
+ x: boundingBox.xCenterPercentage,
12
+ y: boundingBox.yCenterPercentage,
13
+ width: boundingBox.widthPercentage,
14
+ height: boundingBox.heightPercentage,
15
+ inserted_at: new Date().toISOString(),
16
+ conf: 1,
17
+ observation_type: "manual",
18
+ class_name: newClassName,
19
+ event_id: event_id,
20
+ };
21
+ return newTag;
22
+ }
23
+ export function convertTagToBoundingBox(tag, source) {
24
+ const newBoundingBox = {
25
+ xCenterPercentage: tag.x,
26
+ yCenterPercentage: tag.y,
27
+ widthPercentage: tag.width,
28
+ heightPercentage: tag.height,
29
+ label: tag.class_name,
30
+ id: tag.id ? tag.id.toString() : "0",
31
+ left: 0,
32
+ top: 0,
33
+ width: 0,
34
+ height: 0,
35
+ anchorPoint: { x: 0, y: 0 },
36
+ status: SelectionStatus.ARCHIVED,
37
+ source: source,
38
+ };
39
+ return newBoundingBox;
40
+ }
41
+ export function formatBoundingBoxLabel(label) {
42
+ return label;
43
+ }
@@ -0,0 +1,3 @@
1
+ import { SupabaseClient } from "@supabase/supabase-js";
2
+ import { Database } from "../types/supabase";
3
+ export declare function createClientWithApiKey(user_api_key: string): SupabaseClient<Database> | null;
@@ -0,0 +1,22 @@
1
+ import { createClient } from "@supabase/supabase-js";
2
+ export function createClientWithApiKey(user_api_key) {
3
+ const supabase_url = process.env.NEXT_PUBLIC_SUPABASE_URL;
4
+ const supabase_anon_key = process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY;
5
+ if (!supabase_url || !supabase_anon_key) {
6
+ return null;
7
+ }
8
+ // EXCHANGE API KEY FOR JWT
9
+ const supabase_anon = createClient(supabase_url, supabase_anon_key, {
10
+ global: {
11
+ headers: {
12
+ api_key: `${user_api_key}`,
13
+ },
14
+ },
15
+ auth: {
16
+ persistSession: false,
17
+ detectSessionInUrl: false,
18
+ autoRefreshToken: false,
19
+ },
20
+ });
21
+ return supabase_anon;
22
+ }
@@ -0,0 +1,8 @@
1
+ import { IDevice } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ import { SupabaseClient } from "@supabase/supabase-js";
4
+ export declare function get_devices_by_herd(herd_id: number, client: SupabaseClient): Promise<IWebResponseCompatible<IDevice[]>>;
5
+ export declare function get_device_by_id(device_id: number, client?: SupabaseClient): Promise<IWebResponseCompatible<IDevice | null>>;
6
+ export declare function serverUpdateDevice(updatedDevice: IDevice): Promise<IWebResponseCompatible<IDevice | null>>;
7
+ export declare function serverCreateDevice(newDevice: any): Promise<IWebResponseCompatible<IDevice | null>>;
8
+ export declare function serverDeleteDeviceById(device_id: number): Promise<IWebResponseCompatible<IDevice | null>>;
@@ -0,0 +1,92 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { IWebResponse } from "../types/requests";
4
+ export async function get_devices_by_herd(herd_id, client) {
5
+ // call get_devices_for_herd with rpc
6
+ const { data, error } = await client.rpc("get_devices_for_herd", {
7
+ herd_id_caller: herd_id,
8
+ });
9
+ if (!data) {
10
+ return IWebResponse.error("No devices found").to_compatible();
11
+ }
12
+ else {
13
+ let response = IWebResponse.success(data);
14
+ return response.to_compatible();
15
+ }
16
+ }
17
+ export async function get_device_by_id(device_id, client) {
18
+ if (!client) {
19
+ client = await newServerClient();
20
+ }
21
+ const { data, error } = await client.rpc("get_device_by_id", {
22
+ device_id_caller: device_id,
23
+ });
24
+ if (!data) {
25
+ return IWebResponse.error("No device found").to_compatible();
26
+ }
27
+ else {
28
+ let response = IWebResponse.success(data);
29
+ return response.to_compatible();
30
+ }
31
+ }
32
+ export async function serverUpdateDevice(updatedDevice) {
33
+ // delete api keys, latitide, and longitude
34
+ const device_formatted = { ...updatedDevice };
35
+ delete device_formatted.api_keys_scout;
36
+ const device_latitude = device_formatted.latitude;
37
+ const device_longitude = device_formatted.longitude;
38
+ delete device_formatted.latitude;
39
+ delete device_formatted.longitude;
40
+ delete device_formatted.recent_events;
41
+ const supabase = await newServerClient();
42
+ const { data, error } = await supabase
43
+ .from("devices")
44
+ .update(device_formatted)
45
+ .match({ id: device_formatted.id })
46
+ .select("*");
47
+ if (error) {
48
+ return IWebResponse.error(error.message).to_compatible();
49
+ }
50
+ else {
51
+ const updatedDevice = {
52
+ ...data[0],
53
+ latitude: device_latitude,
54
+ longitude: device_longitude,
55
+ };
56
+ return IWebResponse.success(updatedDevice).to_compatible();
57
+ }
58
+ }
59
+ export async function serverCreateDevice(newDevice) {
60
+ const supabase = await newServerClient();
61
+ const user = await supabase.auth.getUser();
62
+ const userId = user?.data?.user?.id;
63
+ newDevice.created_by = userId;
64
+ // strip id field from herd object
65
+ const { data, error } = await supabase
66
+ .from("devices")
67
+ .insert([newDevice])
68
+ .select("*");
69
+ if (error) {
70
+ // TODO: ALLOW PROPERTY INSTANTION OF CPMPATIBLE WEB RESPONSE
71
+ return IWebResponse.error(error.message).to_compatible();
72
+ }
73
+ else {
74
+ const newDevice = { ...data[0], latitude: 0, longitude: 0 };
75
+ return IWebResponse.success(newDevice).to_compatible();
76
+ }
77
+ }
78
+ export async function serverDeleteDeviceById(device_id) {
79
+ const supabase = await newServerClient();
80
+ const { data, error } = await supabase
81
+ .from("devices")
82
+ .delete()
83
+ .match({ id: device_id })
84
+ .select("*");
85
+ if (error) {
86
+ return IWebResponse.error(error.message).to_compatible();
87
+ }
88
+ else {
89
+ const deletedDevice = { ...data[0], latitude: 0, longitude: 0 };
90
+ return IWebResponse.success(deletedDevice).to_compatible();
91
+ }
92
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Ensure email conforms to basic email format x@y.z
3
+ * @param email
4
+ * @returns boolean
5
+ *
6
+ */
7
+ export declare function validateEmail(email: string): boolean;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Ensure email conforms to basic email format x@y.z
3
+ * @param email
4
+ * @returns boolean
5
+ *
6
+ */
7
+ export function validateEmail(email) {
8
+ // emails should be x@y
9
+ const parts = email.split("@");
10
+ if (parts.length !== 2) {
11
+ return false;
12
+ }
13
+ // x should not be empty
14
+ if (parts[0].length === 0) {
15
+ return false;
16
+ }
17
+ // y should have at least one dot
18
+ if (!parts[1].includes(".")) {
19
+ return false;
20
+ }
21
+ return true;
22
+ }
@@ -0,0 +1,6 @@
1
+ import { IEvent } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ export declare function server_get_events_by_herd(herd_id: number): Promise<IWebResponseCompatible<IEvent[]>>;
4
+ export declare function server_get_more_events_by_herd(herd_id: number, offset: number, page_count?: number): Promise<IWebResponseCompatible<IEvent[]>>;
5
+ export declare function server_get_total_events_by_herd(herd_id: number): Promise<IWebResponseCompatible<number>>;
6
+ export declare function server_create_event(newEvent: any): Promise<IWebResponseCompatible<boolean>>;
@@ -0,0 +1,71 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
+ export async function server_get_events_by_herd(herd_id) {
5
+ const supabase = await newServerClient();
6
+ // fetch events and include devices
7
+ // sort by timestamp
8
+ const { data } = await supabase
9
+ .from("events")
10
+ .select(`
11
+ *,
12
+ devices: devices!inner(*)
13
+ `)
14
+ .eq("devices.herd_id", herd_id)
15
+ .order("timestamp_observation", { ascending: false });
16
+ // TODO: DETERMINE WHEN TO PASS ERROR
17
+ let response = IWebResponse.success(data ? data : []);
18
+ return response.to_compatible();
19
+ }
20
+ export async function server_get_more_events_by_herd(herd_id, offset, page_count = 10) {
21
+ const from = offset * page_count;
22
+ const to = from + page_count - 1;
23
+ const supabase = await newServerClient();
24
+ // fetch events and include devices
25
+ // sort by timestamp
26
+ const { data } = await supabase
27
+ .from("events")
28
+ .select(`
29
+ *,
30
+ devices: devices!inner(*)
31
+ `)
32
+ .eq("devices.herd_id", herd_id)
33
+ .range(from, to)
34
+ .order("timestamp_observation", { ascending: false });
35
+ // TODO: DETERMINE WHEN TO PASS ERROR
36
+ let response = IWebResponse.success(data ? data : []);
37
+ return response.to_compatible();
38
+ }
39
+ // function to get total number of events for a herd
40
+ export async function server_get_total_events_by_herd(herd_id) {
41
+ const supabase = await newServerClient();
42
+ // call public.get_total_events_for_herd(herd_id)
43
+ const { data, error } = await supabase.rpc("get_total_events_for_herd", {
44
+ herd_id_caller: herd_id,
45
+ });
46
+ if (error) {
47
+ return {
48
+ status: EnumWebResponse.ERROR,
49
+ msg: error.message,
50
+ data: 0,
51
+ };
52
+ }
53
+ else {
54
+ return IWebResponse.success(data).to_compatible();
55
+ }
56
+ }
57
+ export async function server_create_event(newEvent) {
58
+ const supabase = await newServerClient();
59
+ // strip id field from herd object
60
+ const { data, error } = await supabase.from("events").insert([newEvent]);
61
+ if (error) {
62
+ return {
63
+ status: EnumWebResponse.ERROR,
64
+ msg: error.message,
65
+ data: null,
66
+ };
67
+ }
68
+ else {
69
+ return IWebResponse.success(true).to_compatible();
70
+ }
71
+ }
@@ -0,0 +1,9 @@
1
+ declare function convertToSubcurrency(amount: number, factor?: number): number;
2
+ export declare function roundToTwoDecimals(amount: number): number;
3
+ /**
4
+ * This function takes a number and returns a string with commas and a dollar sign
5
+ * @param amount
6
+ * @returns
7
+ */
8
+ export declare function formatDollarAmountforDisplay(amount: number): string;
9
+ export default convertToSubcurrency;
@@ -0,0 +1,16 @@
1
+ function convertToSubcurrency(amount, factor = 100) {
2
+ return Math.round(amount * factor);
3
+ }
4
+ export function roundToTwoDecimals(amount) {
5
+ return Math.round(amount * 100) / 100;
6
+ }
7
+ /**
8
+ * This function takes a number and returns a string with commas and a dollar sign
9
+ * @param amount
10
+ * @returns
11
+ */
12
+ export function formatDollarAmountforDisplay(amount) {
13
+ // add commas to the number and prefix with $
14
+ return `$${amount.toLocaleString()}`;
15
+ }
16
+ export default convertToSubcurrency;
@@ -0,0 +1,5 @@
1
+ import { ILocationObject } from "../types/gps";
2
+ export default function get_gps_center(gpsList: ILocationObject[]): {
3
+ latitude: number;
4
+ longitude: number;
5
+ };
@@ -0,0 +1,11 @@
1
+ export default function get_gps_center(gpsList) {
2
+ let latitude = 0;
3
+ let longitude = 0;
4
+ gpsList.forEach((gps) => {
5
+ latitude += gps.latitude;
6
+ longitude += gps.longitude;
7
+ });
8
+ latitude /= gpsList.length;
9
+ longitude /= gpsList.length;
10
+ return { latitude, longitude };
11
+ }
@@ -0,0 +1,9 @@
1
+ import { IHerd } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ import { SupabaseClient } from "@supabase/supabase-js";
4
+ import { IHerdModule } from "../types/herd_module";
5
+ export declare function get_herds(client: SupabaseClient): Promise<IWebResponseCompatible<IHerd[]>>;
6
+ export declare function get_herd_by_slug(slug: string): Promise<IWebResponseCompatible<IHerd>>;
7
+ export declare function deleteHerd(herd_id: number): Promise<IWebResponseCompatible<boolean>>;
8
+ export declare function createHerd(newHerd: any): Promise<IWebResponseCompatible<boolean>>;
9
+ export declare function server_load_herd_modules(): Promise<IHerdModule[]>;
@@ -0,0 +1,80 @@
1
+ "use server";
2
+ import { newServerClient } from "../supabase/server";
3
+ import { EnumWebResponse, IWebResponse, } from "../types/requests";
4
+ import { HerdModule } from "../types/herd_module";
5
+ export async function get_herds(client) {
6
+ const { data: herds } = await client.from("herds").select();
7
+ if (!herds) {
8
+ return {
9
+ status: EnumWebResponse.ERROR,
10
+ msg: "No herds found",
11
+ data: null,
12
+ };
13
+ }
14
+ else {
15
+ let response = IWebResponse.success(herds);
16
+ return response.to_compatible();
17
+ }
18
+ }
19
+ export async function get_herd_by_slug(slug) {
20
+ const supabase = await newServerClient();
21
+ const { data: herds } = await supabase
22
+ .from("herds")
23
+ .select()
24
+ .eq("slug", slug)
25
+ .limit(1);
26
+ if (!herds) {
27
+ return {
28
+ status: EnumWebResponse.ERROR,
29
+ msg: "No herds found",
30
+ data: null,
31
+ };
32
+ }
33
+ return IWebResponse.success(herds[0]);
34
+ }
35
+ export async function deleteHerd(herd_id) {
36
+ const supabase = await newServerClient();
37
+ const { error } = await supabase.from("herds").delete().match({ id: 20 });
38
+ if (error) {
39
+ return {
40
+ status: EnumWebResponse.ERROR,
41
+ msg: error.message,
42
+ data: null,
43
+ };
44
+ }
45
+ else {
46
+ return IWebResponse.success(true).to_compatible();
47
+ }
48
+ }
49
+ export async function createHerd(newHerd) {
50
+ const supabase = await newServerClient();
51
+ const user = await supabase.auth.getUser();
52
+ const userId = user?.data?.user?.id;
53
+ newHerd.created_by = userId;
54
+ // strip id field from herd object
55
+ const { data, error } = await supabase.from("herds").insert([newHerd]);
56
+ if (error) {
57
+ return {
58
+ status: EnumWebResponse.ERROR,
59
+ msg: error.message,
60
+ data: null,
61
+ };
62
+ }
63
+ else {
64
+ return IWebResponse.success(true).to_compatible();
65
+ }
66
+ }
67
+ export async function server_load_herd_modules() {
68
+ // load herds
69
+ const client_supabase = await newServerClient();
70
+ let new_herds = await get_herds(client_supabase);
71
+ if (new_herds.status != EnumWebResponse.SUCCESS || !new_herds.data) {
72
+ return [];
73
+ }
74
+ let new_herd_modules = [];
75
+ const herdModulePromises = new_herds.data.map((herd) => HerdModule.from_herd(herd, client_supabase));
76
+ new_herd_modules = await Promise.all(herdModulePromises);
77
+ // now serialize the herd modules
78
+ let serialized_herd_modules = new_herd_modules.map((herd_module) => herd_module.to_serializable());
79
+ return serialized_herd_modules;
80
+ }
@@ -0,0 +1,17 @@
1
+ export * from "./auth";
2
+ export * from "./bounding_boxes";
3
+ export * from "./db";
4
+ export * from "./devices";
5
+ export * from "./email";
6
+ export * from "./events";
7
+ export * from "./finance";
8
+ export * from "./gps";
9
+ export * from "./herds";
10
+ export * from "./location";
11
+ export * from "./plans";
12
+ export * from "./tags";
13
+ export * from "./time";
14
+ export * from "./ui";
15
+ export * from "./users";
16
+ export * from "./web";
17
+ export * from "./zones";
@@ -0,0 +1,17 @@
1
+ export * from "./auth";
2
+ export * from "./bounding_boxes";
3
+ export * from "./db";
4
+ export * from "./devices";
5
+ export * from "./email";
6
+ export * from "./events";
7
+ export * from "./finance";
8
+ export * from "./gps";
9
+ export * from "./herds";
10
+ export * from "./location";
11
+ export * from "./plans";
12
+ export * from "./tags";
13
+ export * from "./time";
14
+ export * from "./ui";
15
+ export * from "./users";
16
+ export * from "./web";
17
+ export * from "./zones";
@@ -0,0 +1 @@
1
+ export declare function format_coordinates_for_db(lat: number, long: number): string;
@@ -0,0 +1,3 @@
1
+ export function format_coordinates_for_db(lat, long) {
2
+ return `POINT(${long} ${lat})`;
3
+ }
@@ -0,0 +1,5 @@
1
+ import { IPlan } from "../types/db";
2
+ import { IWebResponseCompatible } from "../types/requests";
3
+ export declare function server_get_plans_by_herd(herd_id: number): Promise<IWebResponseCompatible<IPlan[]>>;
4
+ export declare function server_create_plans(plans: IPlan[]): Promise<IWebResponseCompatible<IPlan[]>>;
5
+ export declare function server_delete_plans_by_ids(plan_ids: number[]): Promise<IWebResponseCompatible<boolean>>;