@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
@@ -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
  }>;
@@ -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
+ }
@@ -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 { HerdModule, } from "../types/herd_module";
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 client_supabase = await newServerClient();
77
- const herdsResult = await get_herds_with_location(client_supabase);
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
- console.log(`[server_load_herd_modules] No accessible herds (${totalLoadTime}ms)`);
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: totalLoadTime,
116
+ server_processing_time_ms: endTime - startTime,
117
+ content_hash: hashHerdModules([]),
101
118
  };
102
119
  }
103
- const herdModulePromises = herds.map((herd) => HerdModule.from_herd(herd, client_supabase));
104
- const new_herd_modules = await Promise.all(herdModulePromises);
105
- const serialized_herd_modules = new_herd_modules.map((herd_module) => herd_module.to_serializable());
106
- console.log(`[server_load_herd_modules] Loaded ${herds.length} herds in ${totalLoadTime}ms (parallel processing)`);
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
  }
@@ -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";
@@ -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
+ }
@@ -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[]>>>;
@@ -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>>;