ip-finder-client 1.0.15 → 1.0.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/cli.js ADDED
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+ #!/usr/bin/env node
3
+ "use strict";
4
+
5
+ // src/cli.ts
6
+ var import_fs2 = require("fs");
7
+ var import_path2 = require("path");
8
+ var import_os2 = require("os");
9
+
10
+ // src/config.ts
11
+ var import_fs = require("fs");
12
+ var import_path = require("path");
13
+ var import_os = require("os");
14
+ var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".ip-finder");
15
+ var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
16
+ function getApiKeyFromConfig() {
17
+ const envKey = process.env.IP_FINDER_API_KEY;
18
+ if (envKey) {
19
+ return envKey;
20
+ }
21
+ try {
22
+ const content = (0, import_fs.readFileSync)(CONFIG_FILE, "utf-8");
23
+ const config = JSON.parse(content);
24
+ return config.apiKey || null;
25
+ } catch {
26
+ return null;
27
+ }
28
+ }
29
+
30
+ // src/index.ts
31
+ var DEFAULT_BASE_URL = "https://api.ipwhere.site";
32
+ var DEFAULT_TIMEOUT = 1e4;
33
+ var DEFAULT_RETRIES = 2;
34
+ var IPInsightError = class _IPInsightError extends Error {
35
+ statusCode;
36
+ code;
37
+ constructor(message, statusCode, code) {
38
+ super(message);
39
+ this.name = "IPInsightError";
40
+ this.statusCode = statusCode;
41
+ this.code = code;
42
+ Object.setPrototypeOf(this, _IPInsightError.prototype);
43
+ }
44
+ };
45
+ var IPInsight = class {
46
+ apiKey;
47
+ baseUrl;
48
+ timeout;
49
+ retries;
50
+ /** Rate limit info from the last request */
51
+ rateLimit;
52
+ constructor(config) {
53
+ let apiKey = config?.apiKey;
54
+ if (!apiKey) {
55
+ apiKey = getApiKeyFromConfig();
56
+ }
57
+ if (!apiKey) {
58
+ throw new Error(
59
+ 'API key is required. Set it via:\n 1. Constructor: new IPInsight({ apiKey: "your-key" })\n 2. Environment: IP_FINDER_API_KEY=your-key\n 3. Config file: Run "ip-finder setup" or create ~/.ip-finder/config.json'
60
+ );
61
+ }
62
+ this.apiKey = apiKey;
63
+ this.baseUrl = (config?.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
64
+ this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;
65
+ this.retries = config?.retries ?? DEFAULT_RETRIES;
66
+ }
67
+ /**
68
+ * Look up information for an IP address
69
+ *
70
+ * @param ip - IPv4 or IPv6 address to look up
71
+ * @returns IP lookup result with geo, ASN, and network information
72
+ * @throws {IPFinderError} When the API returns an error
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const result = await client.lookup('8.8.8.8');
77
+ * console.log(result.geo?.city); // "Mountain View"
78
+ * console.log(result.asn?.organization); // "Google LLC"
79
+ * ```
80
+ */
81
+ async lookup(ip) {
82
+ if (!ip || typeof ip !== "string") {
83
+ throw new Error("IP address is required and must be a string");
84
+ }
85
+ const url = `${this.baseUrl}/v1/ip/${encodeURIComponent(ip.trim())}`;
86
+ let lastError = null;
87
+ for (let attempt = 0; attempt <= this.retries; attempt++) {
88
+ try {
89
+ const response = await this.fetch(url);
90
+ return response;
91
+ } catch (err) {
92
+ lastError = err;
93
+ if (err instanceof IPInsightError && err.statusCode >= 400 && err.statusCode < 500) {
94
+ throw err;
95
+ }
96
+ if (attempt < this.retries) {
97
+ await this.sleep(Math.pow(2, attempt) * 100);
98
+ }
99
+ }
100
+ }
101
+ throw lastError || new Error("Request failed");
102
+ }
103
+ /**
104
+ * Look up the current request's IP address (useful for "what's my IP" functionality)
105
+ * Note: This requires your API to support a special endpoint for this
106
+ *
107
+ * @returns IP lookup result for the requesting IP
108
+ */
109
+ async lookupSelf() {
110
+ const url = `${this.baseUrl}/v1/ip/me`;
111
+ const response = await this.fetch(url);
112
+ return response;
113
+ }
114
+ /**
115
+ * Batch lookup multiple IP addresses
116
+ *
117
+ * @param ips - Array of IP addresses to look up
118
+ * @returns Array of lookup results (or errors for failed lookups)
119
+ *
120
+ * @example
121
+ * ```ts
122
+ * const results = await client.lookupBatch(['8.8.8.8', '1.1.1.1']);
123
+ * results.forEach(r => console.log(r.ip, r.geo?.country));
124
+ * ```
125
+ */
126
+ async lookupBatch(ips) {
127
+ const results = await Promise.allSettled(
128
+ ips.map((ip) => this.lookup(ip))
129
+ );
130
+ return results.map((result, index) => {
131
+ if (result.status === "fulfilled") {
132
+ return result.value;
133
+ }
134
+ const err = result.reason;
135
+ if (err instanceof IPInsightError) {
136
+ return err;
137
+ }
138
+ return new IPInsightError(
139
+ err?.message || "Unknown error",
140
+ 0,
141
+ "BATCH_ERROR"
142
+ );
143
+ });
144
+ }
145
+ /**
146
+ * Check if the API is healthy and reachable
147
+ *
148
+ * @returns true if the API is healthy
149
+ */
150
+ async healthCheck() {
151
+ try {
152
+ const controller = new AbortController();
153
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
154
+ const response = await fetch(`${this.baseUrl}/healthz`, {
155
+ signal: controller.signal
156
+ });
157
+ clearTimeout(timeoutId);
158
+ return response.ok;
159
+ } catch {
160
+ return false;
161
+ }
162
+ }
163
+ async fetch(url) {
164
+ const controller = new AbortController();
165
+ const timeoutId = setTimeout(() => controller.abort(), this.timeout);
166
+ try {
167
+ const response = await fetch(url, {
168
+ method: "GET",
169
+ headers: {
170
+ "Authorization": `ApiKey ${this.apiKey}`,
171
+ "Accept": "application/json",
172
+ "User-Agent": "ip-finder-client/1.0.0"
173
+ },
174
+ signal: controller.signal
175
+ });
176
+ clearTimeout(timeoutId);
177
+ this.parseRateLimitHeaders(response.headers);
178
+ if (!response.ok) {
179
+ let errorBody = null;
180
+ try {
181
+ errorBody = await response.json();
182
+ } catch {
183
+ }
184
+ throw new IPInsightError(
185
+ errorBody?.error || `HTTP ${response.status}`,
186
+ response.status,
187
+ errorBody?.code
188
+ );
189
+ }
190
+ const data = await response.json();
191
+ return data;
192
+ } catch (err) {
193
+ clearTimeout(timeoutId);
194
+ if (err instanceof IPInsightError) {
195
+ throw err;
196
+ }
197
+ if (err instanceof Error) {
198
+ if (err.name === "AbortError") {
199
+ throw new IPInsightError("Request timeout", 408, "TIMEOUT");
200
+ }
201
+ throw new IPInsightError(err.message, 0, "NETWORK_ERROR");
202
+ }
203
+ throw new IPInsightError("Unknown error", 0, "UNKNOWN");
204
+ }
205
+ }
206
+ parseRateLimitHeaders(headers) {
207
+ const limit = headers.get("X-RateLimit-Limit");
208
+ const remaining = headers.get("X-RateLimit-Remaining");
209
+ const reset = headers.get("X-RateLimit-Reset");
210
+ if (limit && remaining && reset) {
211
+ this.rateLimit = {
212
+ limit: parseInt(limit, 10),
213
+ remaining: parseInt(remaining, 10),
214
+ reset: parseInt(reset, 10)
215
+ };
216
+ }
217
+ }
218
+ sleep(ms) {
219
+ return new Promise((resolve) => setTimeout(resolve, ms));
220
+ }
221
+ };
222
+
223
+ // src/cli.ts
224
+ var CONFIG_DIR2 = (0, import_path2.join)((0, import_os2.homedir)(), ".ip-finder");
225
+ var CONFIG_FILE2 = (0, import_path2.join)(CONFIG_DIR2, "config.json");
226
+ function saveConfig(config) {
227
+ try {
228
+ (0, import_fs2.mkdirSync)(CONFIG_DIR2, { recursive: true });
229
+ (0, import_fs2.writeFileSync)(CONFIG_FILE2, JSON.stringify(config, null, 2), "utf-8");
230
+ console.log(`\u2713 Configuration saved to ${CONFIG_FILE2}`);
231
+ } catch (error) {
232
+ console.error("Failed to save configuration:", error);
233
+ process.exit(1);
234
+ }
235
+ }
236
+ function readInput(prompt) {
237
+ return new Promise((resolve) => {
238
+ process.stdout.write(prompt);
239
+ process.stdin.setEncoding("utf8");
240
+ let input = "";
241
+ process.stdin.once("data", (data) => {
242
+ input = data.toString().trim();
243
+ resolve(input);
244
+ });
245
+ });
246
+ }
247
+ async function setupToken() {
248
+ console.log("\n\u{1F511} IP Finder API Key Setup");
249
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
250
+ console.log("Get your free API key at: https://ipwhere.site/");
251
+ console.log("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n");
252
+ const apiKey = await readInput("Enter your API key: ");
253
+ if (!apiKey || apiKey.trim().length === 0) {
254
+ console.error("\u274C API key cannot be empty");
255
+ process.exit(1);
256
+ }
257
+ const config = { apiKey: apiKey.trim() };
258
+ saveConfig(config);
259
+ return config.apiKey;
260
+ }
261
+ function getApiKey() {
262
+ return getApiKeyFromConfig();
263
+ }
264
+ async function ensureApiKey() {
265
+ let apiKey = getApiKey();
266
+ if (!apiKey) {
267
+ apiKey = await setupToken();
268
+ }
269
+ return apiKey;
270
+ }
271
+ async function main() {
272
+ const args = process.argv.slice(2);
273
+ if (args.length === 0) {
274
+ console.log("Usage: ip-finder <ip-address>");
275
+ console.log(" ip-finder setup");
276
+ process.exit(1);
277
+ }
278
+ if (args[0] === "setup") {
279
+ await setupToken();
280
+ return;
281
+ }
282
+ const ip = args[0];
283
+ const apiKey = await ensureApiKey();
284
+ try {
285
+ const client = new IPInsight({ apiKey });
286
+ const result = await client.lookup(ip);
287
+ console.log(JSON.stringify(result, null, 2));
288
+ } catch (error) {
289
+ if (error instanceof Error) {
290
+ console.error("Error:", error.message);
291
+ } else {
292
+ console.error("Unknown error:", error);
293
+ }
294
+ process.exit(1);
295
+ }
296
+ }
297
+ main().catch((error) => {
298
+ console.error("Fatal error:", error);
299
+ process.exit(1);
300
+ });
@@ -0,0 +1 @@
1
+ export declare function getApiKeyFromConfig(): string | null;
package/dist/index.d.ts CHANGED
@@ -27,7 +27,7 @@ export declare class IPInsight {
27
27
  private readonly retries;
28
28
  /** Rate limit info from the last request */
29
29
  rateLimit?: RateLimitInfo;
30
- constructor(config: IPFinderConfig);
30
+ constructor(config?: IPFinderConfig);
31
31
  /**
32
32
  * Look up information for an IP address
33
33
  *
@@ -93,4 +93,3 @@ export declare class IPInsight {
93
93
  */
94
94
  export declare function createClient(config: IPFinderConfig): IPInsight;
95
95
  export default IPInsight;
96
- //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -26,6 +26,28 @@ __export(src_exports, {
26
26
  default: () => src_default
27
27
  });
28
28
  module.exports = __toCommonJS(src_exports);
29
+
30
+ // src/config.ts
31
+ var import_fs = require("fs");
32
+ var import_path = require("path");
33
+ var import_os = require("os");
34
+ var CONFIG_DIR = (0, import_path.join)((0, import_os.homedir)(), ".ip-finder");
35
+ var CONFIG_FILE = (0, import_path.join)(CONFIG_DIR, "config.json");
36
+ function getApiKeyFromConfig() {
37
+ const envKey = process.env.IP_FINDER_API_KEY;
38
+ if (envKey) {
39
+ return envKey;
40
+ }
41
+ try {
42
+ const content = (0, import_fs.readFileSync)(CONFIG_FILE, "utf-8");
43
+ const config = JSON.parse(content);
44
+ return config.apiKey || null;
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+
50
+ // src/index.ts
29
51
  var DEFAULT_BASE_URL = "https://api.ipwhere.site";
30
52
  var DEFAULT_TIMEOUT = 1e4;
31
53
  var DEFAULT_RETRIES = 2;
@@ -48,13 +70,19 @@ var IPInsight = class {
48
70
  /** Rate limit info from the last request */
49
71
  rateLimit;
50
72
  constructor(config) {
51
- if (!config.apiKey) {
52
- throw new Error("API key is required");
73
+ let apiKey = config?.apiKey;
74
+ if (!apiKey) {
75
+ apiKey = getApiKeyFromConfig();
76
+ }
77
+ if (!apiKey) {
78
+ throw new Error(
79
+ 'API key is required. Set it via:\n 1. Constructor: new IPInsight({ apiKey: "your-key" })\n 2. Environment: IP_FINDER_API_KEY=your-key\n 3. Config file: Run "ip-finder setup" or create ~/.ip-finder/config.json'
80
+ );
53
81
  }
54
- this.apiKey = config.apiKey;
55
- this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
56
- this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
57
- this.retries = config.retries ?? DEFAULT_RETRIES;
82
+ this.apiKey = apiKey;
83
+ this.baseUrl = (config?.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
84
+ this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;
85
+ this.retries = config?.retries ?? DEFAULT_RETRIES;
58
86
  }
59
87
  /**
60
88
  * Look up information for an IP address
package/dist/index.mjs CHANGED
@@ -1,3 +1,23 @@
1
+ // src/config.ts
2
+ import { readFileSync } from "fs";
3
+ import { join } from "path";
4
+ import { homedir } from "os";
5
+ var CONFIG_DIR = join(homedir(), ".ip-finder");
6
+ var CONFIG_FILE = join(CONFIG_DIR, "config.json");
7
+ function getApiKeyFromConfig() {
8
+ const envKey = process.env.IP_FINDER_API_KEY;
9
+ if (envKey) {
10
+ return envKey;
11
+ }
12
+ try {
13
+ const content = readFileSync(CONFIG_FILE, "utf-8");
14
+ const config = JSON.parse(content);
15
+ return config.apiKey || null;
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+
1
21
  // src/index.ts
2
22
  var DEFAULT_BASE_URL = "https://api.ipwhere.site";
3
23
  var DEFAULT_TIMEOUT = 1e4;
@@ -21,13 +41,19 @@ var IPInsight = class {
21
41
  /** Rate limit info from the last request */
22
42
  rateLimit;
23
43
  constructor(config) {
24
- if (!config.apiKey) {
25
- throw new Error("API key is required");
44
+ let apiKey = config?.apiKey;
45
+ if (!apiKey) {
46
+ apiKey = getApiKeyFromConfig();
47
+ }
48
+ if (!apiKey) {
49
+ throw new Error(
50
+ 'API key is required. Set it via:\n 1. Constructor: new IPInsight({ apiKey: "your-key" })\n 2. Environment: IP_FINDER_API_KEY=your-key\n 3. Config file: Run "ip-finder setup" or create ~/.ip-finder/config.json'
51
+ );
26
52
  }
27
- this.apiKey = config.apiKey;
28
- this.baseUrl = (config.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
29
- this.timeout = config.timeout ?? DEFAULT_TIMEOUT;
30
- this.retries = config.retries ?? DEFAULT_RETRIES;
53
+ this.apiKey = apiKey;
54
+ this.baseUrl = (config?.baseUrl || DEFAULT_BASE_URL).replace(/\/$/, "");
55
+ this.timeout = config?.timeout ?? DEFAULT_TIMEOUT;
56
+ this.retries = config?.retries ?? DEFAULT_RETRIES;
31
57
  }
32
58
  /**
33
59
  * Look up information for an IP address
package/dist/types.d.ts CHANGED
@@ -2,8 +2,8 @@
2
2
  * Configuration options for the IP Finder client
3
3
  */
4
4
  export interface IPFinderConfig {
5
- /** Your API key for authentication */
6
- apiKey: string;
5
+ /** Your API key for authentication (optional if set via IP_FINDER_API_KEY env var or config file) */
6
+ apiKey?: string;
7
7
  /** Base URL of the IP Finder API (optional, defaults to https://api.ipwhere.site) */
8
8
  baseUrl?: string;
9
9
  /** Request timeout in milliseconds (default: 10000) */
@@ -138,4 +138,3 @@ export interface RateLimitInfo {
138
138
  remaining: number;
139
139
  reset: number;
140
140
  }
141
- //# sourceMappingURL=types.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ip-finder-client",
3
- "version": "1.0.15",
3
+ "version": "1.0.16",
4
4
  "description": "Lightweight SDK for IP geolocation, ASN lookup, and network information",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -12,16 +12,20 @@
12
12
  "types": "./dist/index.d.ts"
13
13
  }
14
14
  },
15
+ "bin": {
16
+ "ip-finder": "./dist/cli.js"
17
+ },
15
18
  "files": [
16
19
  "dist"
17
20
  ],
18
21
  "scripts": {
19
- "build": "npm run build:cjs && npm run build:esm && npm run build:types",
22
+ "build": "npm run build:cjs && npm run build:esm && npm run build:cli && npm run build:types",
20
23
  "build:cjs": "esbuild src/index.ts --bundle --platform=node --target=node18 --outfile=dist/index.js --format=cjs",
21
24
  "build:esm": "esbuild src/index.ts --bundle --platform=node --target=node18 --outfile=dist/index.mjs --format=esm",
22
- "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist",
25
+ "build:cli": "esbuild src/cli.ts --bundle --platform=node --target=node18 --outfile=dist/cli.js --format=cjs --banner:js='#!/usr/bin/env node'",
26
+ "build:types": "tsc --emitDeclarationOnly --declaration --outDir dist && rm -f dist/*.map",
23
27
  "prepublishOnly": "npm run build",
24
- "deploy": "npm version patch && npm publish",
28
+ "deploy": "npm run build && npm version patch && npm publish",
25
29
  "test": "node test/test.js"
26
30
  },
27
31
  "keywords": [
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EACd,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,GAAG,EACH,OAAO,EACP,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAGjB,YAAY,EACV,cAAc,EACd,cAAc,EACd,QAAQ,EACR,aAAa,EACb,QAAQ,EACR,GAAG,EACH,OAAO,EACP,SAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,WAAW,GACZ,CAAC;AAMF;;GAEG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAgB,UAAU,EAAE,MAAM,CAAC;IACnC,SAAgB,IAAI,CAAC,EAAE,MAAM,CAAC;gBAElB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM;CAO/D;AAED;;;;;;;;;;;GAWG;AACH,qBAAa,SAAS;IACpB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,4CAA4C;IACrC,SAAS,CAAC,EAAE,aAAa,CAAC;gBAErB,MAAM,EAAE,cAAc;IAWlC;;;;;;;;;;;;;OAaG;IACG,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IA+BjD;;;;;OAKG;IACG,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;IAO3C;;;;;;;;;;;OAWG;IACG,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,CAAC,cAAc,GAAG,cAAc,CAAC,EAAE,CAAC;IAqB9E;;;;OAIG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;YAgBvB,KAAK;IAuDnB,OAAO,CAAC,qBAAqB;IAc7B,OAAO,CAAC,KAAK;CAGd;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,SAAS,CAE9D;AAGD,eAAe,SAAS,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,sCAAsC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,GAAG;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,CAAC,EAAE;QACZ,WAAW,CAAC,EAAE,OAAO,CAAC;QACtB,GAAG,CAAC,EAAE,OAAO,CAAC;QACd,GAAG,CAAC,EAAE,OAAO,CAAC;KACf,CAAC;IACF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE;QACJ,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,cAAc,CAAC,EAAE,cAAc,CAAC;QAChC,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,CAAC,EAAE,SAAS,CAAC;IACtB,QAAQ,CAAC,EAAE,QAAQ,CAAC;IACpB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,GAAG,CAAC,EAAE,GAAG,CAAC;IACV,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,WAAW,CAAC;CAC3B;AAED;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf"}