@glowlabs-org/utils 0.2.2 → 0.2.4

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.
@@ -0,0 +1,155 @@
1
+ "use strict";
2
+
3
+ import type {
4
+ Region,
5
+ RegionWithMetadata,
6
+ ActivationConfig,
7
+ CreateRegionPayload,
8
+ } from "../types";
9
+
10
+ // ---------------------------------------------------------------------------
11
+ // Helpers
12
+ // ---------------------------------------------------------------------------
13
+
14
+ function parseApiError(error: unknown): string {
15
+ if (!error) return "Unknown error";
16
+ if (error instanceof Error) return error.message;
17
+ const possible: any = error;
18
+ return possible?.error?.message ?? possible?.message ?? "Unknown error";
19
+ }
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // Factory
23
+ // ---------------------------------------------------------------------------
24
+
25
+ export function useRegionsApi(baseUrl: string) {
26
+ if (!baseUrl) throw new Error("CONTROL API base URL is not set");
27
+
28
+ const request = async <T>(path: string, init?: RequestInit): Promise<T> => {
29
+ const res = await fetch(`${baseUrl}${path}`, init);
30
+ if (!res.ok) {
31
+ const errData = await res.json().catch(() => ({}));
32
+ throw new Error(errData?.error || `Request to ${path} failed`);
33
+ }
34
+ return (await res.json()) as T;
35
+ };
36
+
37
+ // -------------------------------------------------------------------------
38
+ // Local cache / state flags
39
+ // -------------------------------------------------------------------------
40
+ let cachedRegions: Region[] = [];
41
+ let isLoading = false;
42
+ let isCreatingRegion = false;
43
+
44
+ // -------------------------------------------------------------------------
45
+ // Queries
46
+ // -------------------------------------------------------------------------
47
+ const fetchRegions = async (): Promise<Region[]> => {
48
+ isLoading = true;
49
+ try {
50
+ const data = await request<{ regions: Region[] }>(`/regions`);
51
+ cachedRegions = data.regions ?? [];
52
+ return cachedRegions;
53
+ } catch (error) {
54
+ throw new Error(parseApiError(error));
55
+ } finally {
56
+ isLoading = false;
57
+ }
58
+ };
59
+
60
+ const fetchActivationConfig = async (
61
+ regionCode: string
62
+ ): Promise<ActivationConfig> => {
63
+ try {
64
+ return await request<ActivationConfig>(
65
+ `/regions/activation-config?code=${regionCode}`
66
+ );
67
+ } catch (error) {
68
+ throw new Error(parseApiError(error));
69
+ }
70
+ };
71
+
72
+ // -------------------------------------------------------------------------
73
+ // Mutations
74
+ // -------------------------------------------------------------------------
75
+ const createRegion = async (payload: CreateRegionPayload): Promise<void> => {
76
+ isCreatingRegion = true;
77
+ try {
78
+ await request(`/regions/create`, {
79
+ method: "POST",
80
+ headers: { "Content-Type": "application/json" },
81
+ body: JSON.stringify(payload),
82
+ });
83
+ // Refresh the local cache after successful creation
84
+ await fetchRegions();
85
+ } catch (error) {
86
+ throw new Error(parseApiError(error));
87
+ } finally {
88
+ isCreatingRegion = false;
89
+ }
90
+ };
91
+
92
+ // -------------------------------------------------------------------------
93
+ // Helpers (derived)
94
+ // -------------------------------------------------------------------------
95
+ // NOTE: regionMetadata is imported lazily to avoid circular deps at load time.
96
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
97
+ const { regionMetadata } = require("@/lib/region-metadata");
98
+
99
+ const getRegionByCode = (code: string): RegionWithMetadata | null => {
100
+ const metadata = regionMetadata[code];
101
+ if (!metadata) return null;
102
+
103
+ const existingRegion = cachedRegions.find(
104
+ (r) => r.name.toLowerCase() === metadata.name.toLowerCase()
105
+ );
106
+
107
+ if (existingRegion) {
108
+ return {
109
+ ...existingRegion,
110
+ code: metadata.code,
111
+ description: metadata.description,
112
+ flag: metadata.flag,
113
+ };
114
+ }
115
+
116
+ // Placeholder if region does not yet exist in DB
117
+ return {
118
+ id: -1,
119
+ name: metadata.name,
120
+ code: metadata.code,
121
+ description: metadata.description,
122
+ flag: metadata.flag,
123
+ isUs: metadata.isUs,
124
+ isActive: false,
125
+ stake: "0",
126
+ stakeProgress: 0,
127
+ solarFarmCount: 0,
128
+ solarFarmProgress: 0,
129
+ installerCount: 0,
130
+ installerProgress: 0,
131
+ };
132
+ };
133
+
134
+ // -------------------------------------------------------------------------
135
+ // Public API
136
+ // -------------------------------------------------------------------------
137
+ return {
138
+ // Data access
139
+ fetchRegions,
140
+ fetchActivationConfig,
141
+ getRegionByCode,
142
+ createRegion,
143
+
144
+ // Cached data & flags
145
+ get regions() {
146
+ return cachedRegions;
147
+ },
148
+ get isLoading() {
149
+ return isLoading;
150
+ },
151
+ get isCreatingRegion() {
152
+ return isCreatingRegion;
153
+ },
154
+ } as const;
155
+ }