@glubean/sdk 0.1.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.
- package/dist/configure.d.ts +141 -0
- package/dist/configure.d.ts.map +1 -0
- package/dist/configure.js +535 -0
- package/dist/configure.js.map +1 -0
- package/dist/data.d.ts +232 -0
- package/dist/data.d.ts.map +1 -0
- package/dist/data.js +543 -0
- package/dist/data.js.map +1 -0
- package/dist/expect.d.ts +511 -0
- package/dist/expect.d.ts.map +1 -0
- package/dist/expect.js +763 -0
- package/dist/expect.js.map +1 -0
- package/dist/index.d.ts +718 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1015 -0
- package/dist/index.js.map +1 -0
- package/dist/internal.d.ts +39 -0
- package/dist/internal.d.ts.map +1 -0
- package/dist/internal.js +52 -0
- package/dist/internal.js.map +1 -0
- package/dist/plugin.d.ts +56 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/plugin.js +57 -0
- package/dist/plugin.js.map +1 -0
- package/dist/types.d.ts +1971 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +54 -0
- package/dist/types.js.map +1 -0
- package/package.json +40 -0
package/dist/data.js
ADDED
|
@@ -0,0 +1,543 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Data loading utilities for test.each data-driven tests.
|
|
3
|
+
*
|
|
4
|
+
* These helpers load test data from various file formats and directories,
|
|
5
|
+
* returning plain arrays suitable for `test.each()`.
|
|
6
|
+
*
|
|
7
|
+
* All paths are **relative to the project root** (the directory containing
|
|
8
|
+
* `package.json`). The runner guarantees that `process.cwd()` points to the
|
|
9
|
+
* project root at execution time.
|
|
10
|
+
*
|
|
11
|
+
* @module data
|
|
12
|
+
*
|
|
13
|
+
* @example Load JSON (use native import instead)
|
|
14
|
+
* ```ts
|
|
15
|
+
* import cases from "./data/cases.json" with { type: "json" };
|
|
16
|
+
* export const tests = test.each(cases)("case-$id", fn);
|
|
17
|
+
* ```
|
|
18
|
+
*
|
|
19
|
+
* @example Load CSV
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { test, fromCsv } from "@glubean/sdk";
|
|
22
|
+
* export const tests = test.each(await fromCsv("./data/cases.csv"))
|
|
23
|
+
* ("case-$id", async (ctx, row) => { ... });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* @example Load YAML
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { test, fromYaml } from "@glubean/sdk";
|
|
29
|
+
* export const tests = test.each(await fromYaml("./data/cases.yaml"))
|
|
30
|
+
* ("case-$id", async (ctx, row) => { ... });
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @example Load JSONL
|
|
34
|
+
* ```ts
|
|
35
|
+
* import { test, fromJsonl } from "@glubean/sdk";
|
|
36
|
+
* export const tests = test.each(await fromJsonl("./data/requests.jsonl"))
|
|
37
|
+
* ("req-$index", async (ctx, row) => { ... });
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* @example Load directory of files
|
|
41
|
+
* ```ts
|
|
42
|
+
* import { test, fromDir } from "@glubean/sdk";
|
|
43
|
+
* export const tests = test.each(await fromDir("./cases/"))
|
|
44
|
+
* ("case-$_name", async (ctx, row) => { ... });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
import { readFile, readdir } from "node:fs/promises";
|
|
48
|
+
import { resolve } from "node:path";
|
|
49
|
+
import { parse as parseYaml } from "yaml";
|
|
50
|
+
// =============================================================================
|
|
51
|
+
// Shared utilities
|
|
52
|
+
// =============================================================================
|
|
53
|
+
function safeCwd() {
|
|
54
|
+
try {
|
|
55
|
+
return process.cwd();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return "(unavailable)";
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function formatPathErrorContext(path, action, error) {
|
|
62
|
+
const cwd = safeCwd();
|
|
63
|
+
const resolvedPath = cwd === "(unavailable)" ? path : resolve(cwd, path);
|
|
64
|
+
const cause = error instanceof Error ? error : undefined;
|
|
65
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
66
|
+
return new Error(`Failed to ${action}: "${path}".\n` +
|
|
67
|
+
`Current working directory: ${cwd}\n` +
|
|
68
|
+
`Resolved path: ${resolvedPath}\n` +
|
|
69
|
+
'Hint: data loader paths are resolved from project root (where "package.json" is).\n' +
|
|
70
|
+
'Hint: if your file is in the standard data folder, use a path like "./data/cases.csv".\n' +
|
|
71
|
+
`Cause: ${reason}`, cause ? { cause } : undefined);
|
|
72
|
+
}
|
|
73
|
+
async function readTextFileWithContext(path) {
|
|
74
|
+
try {
|
|
75
|
+
return await readFile(path, "utf-8");
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw formatPathErrorContext(path, "read file", error);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function parseJsonWithContext(path, content) {
|
|
82
|
+
try {
|
|
83
|
+
return JSON.parse(content);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
throw formatPathErrorContext(path, "parse JSON file", error);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Normalize `string | string[]` to `string[]`.
|
|
91
|
+
* @internal
|
|
92
|
+
*/
|
|
93
|
+
export function toArray(value) {
|
|
94
|
+
if (!value)
|
|
95
|
+
return [];
|
|
96
|
+
return Array.isArray(value) ? value : [value];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Resolve a dot-separated path into a nested object.
|
|
100
|
+
* Returns `undefined` if any segment is missing.
|
|
101
|
+
*
|
|
102
|
+
* @internal
|
|
103
|
+
* @example
|
|
104
|
+
* pickByPath({ a: { b: [1, 2] } }, "a.b") // → [1, 2]
|
|
105
|
+
*/
|
|
106
|
+
function pickByPath(obj, path) {
|
|
107
|
+
let current = obj;
|
|
108
|
+
for (const segment of path.split(".")) {
|
|
109
|
+
if (current == null || typeof current !== "object")
|
|
110
|
+
return undefined;
|
|
111
|
+
current = current[segment];
|
|
112
|
+
}
|
|
113
|
+
return current;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Extract an array from parsed data using an optional `pick` path.
|
|
117
|
+
* If no pick is provided, the data must be a top-level array.
|
|
118
|
+
* Provides helpful error messages when the data shape is unexpected.
|
|
119
|
+
*
|
|
120
|
+
* @internal
|
|
121
|
+
*/
|
|
122
|
+
function extractArray(data, pick, sourcePath) {
|
|
123
|
+
if (pick) {
|
|
124
|
+
const picked = pickByPath(data, pick);
|
|
125
|
+
if (!Array.isArray(picked)) {
|
|
126
|
+
throw new Error(`${sourcePath}: pick path "${pick}" did not resolve to an array. ` +
|
|
127
|
+
`Got: ${picked === undefined ? "undefined" : typeof picked}`);
|
|
128
|
+
}
|
|
129
|
+
return picked;
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(data)) {
|
|
132
|
+
return data;
|
|
133
|
+
}
|
|
134
|
+
// Data is an object — provide helpful error with discovered array fields
|
|
135
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
136
|
+
const arrayFields = [];
|
|
137
|
+
for (const [key, value] of Object.entries(data)) {
|
|
138
|
+
if (Array.isArray(value)) {
|
|
139
|
+
arrayFields.push(`"${key}" (${value.length} items)`);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
const hint = arrayFields.length > 0
|
|
143
|
+
? `\nFound these array fields: ${arrayFields.join(", ")}` +
|
|
144
|
+
`\nHint: use { pick: "${arrayFields[0]?.match(/"([^"]+)"/)?.[1] ?? ""}" } to select one.`
|
|
145
|
+
: "\nNo array fields found at the top level.";
|
|
146
|
+
throw new Error(`${sourcePath}: root is an object, not an array.${hint}`);
|
|
147
|
+
}
|
|
148
|
+
throw new Error(`${sourcePath}: expected an array, got ${typeof data}`);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Load test data from a CSV file.
|
|
152
|
+
*
|
|
153
|
+
* Returns an array of records. All values are strings (CSV has no type info).
|
|
154
|
+
* Use the returned data with `test.each()` for data-driven tests.
|
|
155
|
+
*
|
|
156
|
+
* @param path Path to the CSV file, relative to project root
|
|
157
|
+
* @param options CSV parsing options
|
|
158
|
+
* @returns Array of row objects
|
|
159
|
+
*
|
|
160
|
+
* @example Basic usage
|
|
161
|
+
* ```ts
|
|
162
|
+
* import { test, fromCsv } from "@glubean/sdk";
|
|
163
|
+
*
|
|
164
|
+
* export const tests = test.each(await fromCsv("./data/cases.csv"))
|
|
165
|
+
* ("case-$index-$country", async (ctx, row) => {
|
|
166
|
+
* const res = await ctx.http.get(`${ctx.vars.require("BASE_URL")}/users/${row.id}`);
|
|
167
|
+
* ctx.assert(res.status === row.expected, "status check");
|
|
168
|
+
* });
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* @example Custom separator
|
|
172
|
+
* ```ts
|
|
173
|
+
* const data = await fromCsv("./data/cases.tsv", { separator: "\t" });
|
|
174
|
+
* ```
|
|
175
|
+
*/
|
|
176
|
+
export async function fromCsv(path, options) {
|
|
177
|
+
const content = await readTextFileWithContext(path);
|
|
178
|
+
const separator = options?.separator ?? ",";
|
|
179
|
+
const hasHeaders = options?.headers !== false;
|
|
180
|
+
const lines = content.split("\n").filter((line) => line.trim() !== "");
|
|
181
|
+
if (lines.length === 0)
|
|
182
|
+
return [];
|
|
183
|
+
const parseLine = (line) => {
|
|
184
|
+
const fields = [];
|
|
185
|
+
let current = "";
|
|
186
|
+
let inQuotes = false;
|
|
187
|
+
for (let i = 0; i < line.length; i++) {
|
|
188
|
+
const char = line[i];
|
|
189
|
+
if (inQuotes) {
|
|
190
|
+
if (char === '"') {
|
|
191
|
+
if (i + 1 < line.length && line[i + 1] === '"') {
|
|
192
|
+
current += '"';
|
|
193
|
+
i++; // Skip escaped quote
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
inQuotes = false;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
current += char;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
if (char === '"') {
|
|
205
|
+
inQuotes = true;
|
|
206
|
+
}
|
|
207
|
+
else if (char === separator) {
|
|
208
|
+
fields.push(current.trim());
|
|
209
|
+
current = "";
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
current += char;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
fields.push(current.trim());
|
|
217
|
+
return fields;
|
|
218
|
+
};
|
|
219
|
+
if (hasHeaders) {
|
|
220
|
+
const headers = parseLine(lines[0]);
|
|
221
|
+
return lines.slice(1).map((line) => {
|
|
222
|
+
const values = parseLine(line);
|
|
223
|
+
const record = {};
|
|
224
|
+
for (let i = 0; i < headers.length; i++) {
|
|
225
|
+
record[headers[i]] = values[i] ?? "";
|
|
226
|
+
}
|
|
227
|
+
return record;
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
return lines.map((line) => {
|
|
232
|
+
const values = parseLine(line);
|
|
233
|
+
const record = {};
|
|
234
|
+
for (let i = 0; i < values.length; i++) {
|
|
235
|
+
record[String(i)] = values[i];
|
|
236
|
+
}
|
|
237
|
+
return record;
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Load test data from a YAML file.
|
|
243
|
+
*
|
|
244
|
+
* The file must contain a top-level array, or use the `pick` option
|
|
245
|
+
* to specify the dot-path to an array within the document.
|
|
246
|
+
*
|
|
247
|
+
* @param path Path to the YAML file, relative to project root
|
|
248
|
+
* @param options YAML loading options
|
|
249
|
+
* @returns Array of row objects
|
|
250
|
+
*
|
|
251
|
+
* @example Top-level array
|
|
252
|
+
* ```ts
|
|
253
|
+
* // cases.yaml:
|
|
254
|
+
* // - id: 1
|
|
255
|
+
* // expected: 200
|
|
256
|
+
* // - id: 999
|
|
257
|
+
* // expected: 404
|
|
258
|
+
*
|
|
259
|
+
* import { test, fromYaml } from "@glubean/sdk";
|
|
260
|
+
* export const tests = test.each(await fromYaml("./data/cases.yaml"))
|
|
261
|
+
* ("case-$id", async (ctx, row) => { ... });
|
|
262
|
+
* ```
|
|
263
|
+
*
|
|
264
|
+
* @example Nested array with pick
|
|
265
|
+
* ```ts
|
|
266
|
+
* // collection.yaml:
|
|
267
|
+
* // info:
|
|
268
|
+
* // name: API Tests
|
|
269
|
+
* // testCases:
|
|
270
|
+
* // - id: 1
|
|
271
|
+
* // expected: 200
|
|
272
|
+
*
|
|
273
|
+
* const data = await fromYaml("./data/collection.yaml", { pick: "testCases" });
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
export async function fromYaml(path, options) {
|
|
277
|
+
const content = await readTextFileWithContext(path);
|
|
278
|
+
const data = parseYaml(content);
|
|
279
|
+
return extractArray(data, options?.pick, path);
|
|
280
|
+
}
|
|
281
|
+
// =============================================================================
|
|
282
|
+
// JSONL loader
|
|
283
|
+
// =============================================================================
|
|
284
|
+
/**
|
|
285
|
+
* Load test data from a JSONL (JSON Lines) file.
|
|
286
|
+
*
|
|
287
|
+
* Each line must be a valid JSON object. Empty lines are skipped.
|
|
288
|
+
*
|
|
289
|
+
* @param path Path to the JSONL file, relative to project root
|
|
290
|
+
* @returns Array of row objects
|
|
291
|
+
*
|
|
292
|
+
* @example
|
|
293
|
+
* ```ts
|
|
294
|
+
* // requests.jsonl:
|
|
295
|
+
* // {"method":"GET","url":"/users/1","expected":200}
|
|
296
|
+
* // {"method":"GET","url":"/users/999","expected":404}
|
|
297
|
+
*
|
|
298
|
+
* import { test, fromJsonl } from "@glubean/sdk";
|
|
299
|
+
* export const tests = test.each(await fromJsonl("./data/requests.jsonl"))
|
|
300
|
+
* ("req-$index", async (ctx, row) => { ... });
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
export async function fromJsonl(path) {
|
|
304
|
+
const content = await readTextFileWithContext(path);
|
|
305
|
+
const lines = content.split("\n").filter((line) => line.trim() !== "");
|
|
306
|
+
return lines.map((line, index) => {
|
|
307
|
+
try {
|
|
308
|
+
return JSON.parse(line);
|
|
309
|
+
}
|
|
310
|
+
catch {
|
|
311
|
+
throw new Error(`${path}: invalid JSON at line ${index + 1}: ${line.substring(0, 80)}`);
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Load test data from a directory of files.
|
|
317
|
+
*
|
|
318
|
+
* Each file becomes one row in the data table. The file contents are spread
|
|
319
|
+
* into the row, plus `_name` (filename without extension) and `_path`
|
|
320
|
+
* (relative path) are auto-injected.
|
|
321
|
+
*
|
|
322
|
+
* For other modes, use `fromDir.concat()` or `fromDir.merge()`.
|
|
323
|
+
*
|
|
324
|
+
* Supported file types: `.json`, `.yaml`, `.yml`, `.jsonl`, `.csv`.
|
|
325
|
+
*
|
|
326
|
+
* @param path Path to the directory, relative to project root
|
|
327
|
+
* @param options Directory loading options
|
|
328
|
+
* @returns Array of row objects (one per file)
|
|
329
|
+
*
|
|
330
|
+
* @example One file = one test
|
|
331
|
+
* ```ts
|
|
332
|
+
* // cases/
|
|
333
|
+
* // user-1.json → { "id": 1, "expected": 200 }
|
|
334
|
+
* // user-999.json → { "id": 999, "expected": 404 }
|
|
335
|
+
*
|
|
336
|
+
* import { test, fromDir } from "@glubean/sdk";
|
|
337
|
+
* export const tests = test.each(await fromDir("./cases/"))
|
|
338
|
+
* ("case-$_name", async (ctx, row) => {
|
|
339
|
+
* const res = await ctx.http.get(`${ctx.vars.require("BASE_URL")}/users/${row.id}`);
|
|
340
|
+
* ctx.assert(res.status === row.expected, "status check");
|
|
341
|
+
* });
|
|
342
|
+
* ```
|
|
343
|
+
*/
|
|
344
|
+
export async function fromDir(path, options) {
|
|
345
|
+
const files = await _collectAndSort(path, options);
|
|
346
|
+
if (files.length === 0) {
|
|
347
|
+
return [];
|
|
348
|
+
}
|
|
349
|
+
const result = [];
|
|
350
|
+
for (const filePath of files) {
|
|
351
|
+
const content = await loadSingleFileAsObject(filePath);
|
|
352
|
+
const name = fileNameWithoutExt(filePath);
|
|
353
|
+
const relativePath = filePath.startsWith(path) ? filePath.slice(path.length).replace(/^\//, "") : filePath;
|
|
354
|
+
result.push({
|
|
355
|
+
_name: name,
|
|
356
|
+
_path: relativePath,
|
|
357
|
+
...content,
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
return result;
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* Concatenate arrays from all files in a directory into one flat table.
|
|
364
|
+
*
|
|
365
|
+
* Each file should contain an array. All arrays are concatenated.
|
|
366
|
+
* Use `pick` to extract a nested array from each file.
|
|
367
|
+
*
|
|
368
|
+
* @param path Path to the directory, relative to project root
|
|
369
|
+
* @param options Directory loading options (supports `pick` for nested arrays)
|
|
370
|
+
* @returns One flat array with rows from all files
|
|
371
|
+
*
|
|
372
|
+
* @example
|
|
373
|
+
* ```ts
|
|
374
|
+
* // batches/
|
|
375
|
+
* // batch-001.json → [{ id: 1, ... }, { id: 2, ... }]
|
|
376
|
+
* // batch-002.json → [{ id: 3, ... }, { id: 4, ... }]
|
|
377
|
+
*
|
|
378
|
+
* export const tests = test.each(await fromDir.concat("./batches/"))
|
|
379
|
+
* ("case-$id", async (ctx, row) => { ... });
|
|
380
|
+
* ```
|
|
381
|
+
*
|
|
382
|
+
* @example YAML with pick
|
|
383
|
+
* ```ts
|
|
384
|
+
* const data = await fromDir.concat("./specs/", {
|
|
385
|
+
* ext: ".yaml",
|
|
386
|
+
* pick: "cases",
|
|
387
|
+
* });
|
|
388
|
+
* ```
|
|
389
|
+
*/
|
|
390
|
+
fromDir.concat = async function fromDirConcat(path, options) {
|
|
391
|
+
const files = await _collectAndSort(path, options);
|
|
392
|
+
if (files.length === 0) {
|
|
393
|
+
return [];
|
|
394
|
+
}
|
|
395
|
+
const result = [];
|
|
396
|
+
for (const filePath of files) {
|
|
397
|
+
const fileData = await loadFileAuto(filePath, options?.pick);
|
|
398
|
+
result.push(...fileData);
|
|
399
|
+
}
|
|
400
|
+
return result;
|
|
401
|
+
};
|
|
402
|
+
/**
|
|
403
|
+
* Merge objects from all files in a directory into one combined map.
|
|
404
|
+
*
|
|
405
|
+
* Each file should contain a JSON/YAML object with named keys.
|
|
406
|
+
* All keys are shallow-merged; later files override earlier ones
|
|
407
|
+
* (files are sorted alphabetically).
|
|
408
|
+
*
|
|
409
|
+
* Designed for `test.pick` where named examples are split across files
|
|
410
|
+
* (e.g. by region, environment, or tenant).
|
|
411
|
+
*
|
|
412
|
+
* @param path Path to the directory, relative to project root
|
|
413
|
+
* @param options Directory loading options
|
|
414
|
+
* @returns A single merged object containing all keys from all files
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* ```ts
|
|
418
|
+
* // data/regions/
|
|
419
|
+
* // us-east.json → { "us-east-1": {...}, "us-east-2": {...} }
|
|
420
|
+
* // eu-west.json → { "eu-west-1": {...} }
|
|
421
|
+
*
|
|
422
|
+
* const allRegions = await fromDir.merge("./data/regions/");
|
|
423
|
+
* // → { "us-east-1": {...}, "us-east-2": {...}, "eu-west-1": {...} }
|
|
424
|
+
*
|
|
425
|
+
* export const regionTest = test.pick(allRegions)
|
|
426
|
+
* ("region-$_pick", async (ctx, data) => { ... });
|
|
427
|
+
* ```
|
|
428
|
+
*/
|
|
429
|
+
fromDir.merge = async function fromDirMerge(path, options) {
|
|
430
|
+
const files = await _collectAndSort(path, options);
|
|
431
|
+
const result = {};
|
|
432
|
+
for (const filePath of files) {
|
|
433
|
+
const content = await loadSingleFileAsObject(filePath);
|
|
434
|
+
Object.assign(result, content);
|
|
435
|
+
}
|
|
436
|
+
return result;
|
|
437
|
+
};
|
|
438
|
+
/**
|
|
439
|
+
* Collect and sort files from a directory.
|
|
440
|
+
* Shared by all fromDir modes.
|
|
441
|
+
* @internal
|
|
442
|
+
*/
|
|
443
|
+
async function _collectAndSort(path, options) {
|
|
444
|
+
const extensions = toArray(options?.ext || ".json");
|
|
445
|
+
const recursive = options?.recursive ?? false;
|
|
446
|
+
const files = [];
|
|
447
|
+
await collectFiles(path, extensions, recursive, files);
|
|
448
|
+
files.sort();
|
|
449
|
+
return files;
|
|
450
|
+
}
|
|
451
|
+
// =============================================================================
|
|
452
|
+
// Internal helpers for fromDir
|
|
453
|
+
// =============================================================================
|
|
454
|
+
/**
|
|
455
|
+
* Recursively collect files matching the given extensions.
|
|
456
|
+
* @internal
|
|
457
|
+
*/
|
|
458
|
+
async function collectFiles(dir, extensions, recursive, result) {
|
|
459
|
+
try {
|
|
460
|
+
const entries = await readdir(dir, { withFileTypes: true });
|
|
461
|
+
for (const entry of entries) {
|
|
462
|
+
const fullPath = dir.endsWith("/") ? `${dir}${entry.name}` : `${dir}/${entry.name}`;
|
|
463
|
+
if (entry.isFile()) {
|
|
464
|
+
const matchesExt = extensions.some((ext) => entry.name.toLowerCase().endsWith(ext.toLowerCase()));
|
|
465
|
+
if (matchesExt) {
|
|
466
|
+
result.push(fullPath);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
else if (entry.isDirectory() && recursive) {
|
|
470
|
+
await collectFiles(fullPath, extensions, recursive, result);
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
throw formatPathErrorContext(dir, "read directory", error);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/**
|
|
479
|
+
* Load a single file as an array of rows, auto-detecting format.
|
|
480
|
+
* Used in concat mode.
|
|
481
|
+
* @internal
|
|
482
|
+
*/
|
|
483
|
+
async function loadFileAuto(filePath, pick) {
|
|
484
|
+
const lower = filePath.toLowerCase();
|
|
485
|
+
if (lower.endsWith(".csv")) {
|
|
486
|
+
return (await fromCsv(filePath));
|
|
487
|
+
}
|
|
488
|
+
if (lower.endsWith(".jsonl")) {
|
|
489
|
+
return await fromJsonl(filePath);
|
|
490
|
+
}
|
|
491
|
+
if (lower.endsWith(".yaml") || lower.endsWith(".yml")) {
|
|
492
|
+
return await fromYaml(filePath, { pick });
|
|
493
|
+
}
|
|
494
|
+
// Default: JSON
|
|
495
|
+
const content = await readTextFileWithContext(filePath);
|
|
496
|
+
const data = parseJsonWithContext(filePath, content);
|
|
497
|
+
return extractArray(data, pick, filePath);
|
|
498
|
+
}
|
|
499
|
+
/**
|
|
500
|
+
* Load a single file as one object (for default fromDir mode).
|
|
501
|
+
* @internal
|
|
502
|
+
*/
|
|
503
|
+
async function loadSingleFileAsObject(filePath) {
|
|
504
|
+
const lower = filePath.toLowerCase();
|
|
505
|
+
const content = await readTextFileWithContext(filePath);
|
|
506
|
+
if (lower.endsWith(".yaml") || lower.endsWith(".yml")) {
|
|
507
|
+
const data = parseYaml(content);
|
|
508
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
509
|
+
return data;
|
|
510
|
+
}
|
|
511
|
+
return { data };
|
|
512
|
+
}
|
|
513
|
+
if (lower.endsWith(".jsonl")) {
|
|
514
|
+
// JSONL in single-file mode: return first line as the object
|
|
515
|
+
const firstLine = content.split("\n").find((l) => l.trim() !== "");
|
|
516
|
+
if (firstLine) {
|
|
517
|
+
return JSON.parse(firstLine);
|
|
518
|
+
}
|
|
519
|
+
return {};
|
|
520
|
+
}
|
|
521
|
+
if (lower.endsWith(".csv")) {
|
|
522
|
+
// CSV in single-file mode: return first row as the object
|
|
523
|
+
const rows = await fromCsv(filePath);
|
|
524
|
+
return rows[0] ?? {};
|
|
525
|
+
}
|
|
526
|
+
// Default: JSON
|
|
527
|
+
const data = JSON.parse(content);
|
|
528
|
+
if (data && typeof data === "object" && !Array.isArray(data)) {
|
|
529
|
+
return data;
|
|
530
|
+
}
|
|
531
|
+
return { data };
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Extract filename without extension.
|
|
535
|
+
* @internal
|
|
536
|
+
*/
|
|
537
|
+
function fileNameWithoutExt(filePath) {
|
|
538
|
+
const parts = filePath.split("/");
|
|
539
|
+
const filename = parts[parts.length - 1];
|
|
540
|
+
const lastDot = filename.lastIndexOf(".");
|
|
541
|
+
return lastDot === -1 ? filename : filename.substring(0, lastDot);
|
|
542
|
+
}
|
|
543
|
+
//# sourceMappingURL=data.js.map
|
package/dist/data.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.js","sourceRoot":"","sources":["../src/data.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AAEH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;AAE1C,gFAAgF;AAChF,mBAAmB;AACnB,gFAAgF;AAEhF,SAAS,OAAO;IACd,IAAI,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,eAAe,CAAC;IACzB,CAAC;AACH,CAAC;AAED,SAAS,sBAAsB,CAC7B,IAAY,EACZ,MAA0D,EAC1D,KAAc;IAEd,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IACtB,MAAM,YAAY,GAAG,GAAG,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACzE,MAAM,KAAK,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IACzD,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEtE,OAAO,IAAI,KAAK,CACd,aAAa,MAAM,MAAM,IAAI,MAAM;QACjC,8BAA8B,GAAG,IAAI;QACrC,kBAAkB,YAAY,IAAI;QAClC,qFAAqF;QACrF,0FAA0F;QAC1F,UAAU,MAAM,EAAE,EACpB,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAC9B,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,uBAAuB,CAAC,IAAY;IACjD,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IACvC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,sBAAsB,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAAC,IAAY,EAAE,OAAe;IACzD,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC7B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,EAAE,KAAK,CAAC,CAAC;IAC/D,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,KAAoC;IAC1D,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,UAAU,CAAC,GAAY,EAAE,IAAY;IAC5C,IAAI,OAAO,GAAG,GAAG,CAAC;IAClB,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACtC,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,OAAO,KAAK,QAAQ;YAAE,OAAO,SAAS,CAAC;QACrE,OAAO,GAAI,OAAmC,CAAC,OAAO,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,YAAY,CACnB,IAAa,EACb,IAAwB,EACxB,UAAkB;IAElB,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC3B,MAAM,IAAI,KAAK,CACb,GAAG,UAAU,gBAAgB,IAAI,iCAAiC;gBAChE,QAAQ,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,MAAM,EAAE,CAC/D,CAAC;QACJ,CAAC;QACD,OAAO,MAAa,CAAC;IACvB,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,OAAO,IAAW,CAAC;IACrB,CAAC;IAED,yEAAyE;IACzE,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,KACE,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAClC,IAA+B,CAChC,EACD,CAAC;YACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;gBACzB,WAAW,CAAC,IAAI,CAAC,IAAI,GAAG,MAAM,KAAK,CAAC,MAAM,SAAS,CAAC,CAAC;YACvD,CAAC;QACH,CAAC;QACD,MAAM,IAAI,GAAG,WAAW,CAAC,MAAM,GAAG,CAAC;YACjC,CAAC,CAAC,+BAA+B,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;gBACvD,wBAAwB,WAAW,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,oBAAoB;YAC3F,CAAC,CAAC,2CAA2C,CAAC;QAEhD,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,qCAAqC,IAAI,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,GAAG,UAAU,4BAA4B,OAAO,IAAI,EAAE,CAAC,CAAC;AAC1E,CAAC;AA2BD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAE3B,IAAY,EAAE,OAAwB;IACtC,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,GAAG,CAAC;IAC5C,MAAM,UAAU,GAAG,OAAO,EAAE,OAAO,KAAK,KAAK,CAAC;IAE9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAElC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAY,EAAE;QAC3C,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;QACjB,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACrC,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACjB,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;wBAC/C,OAAO,IAAI,GAAG,CAAC;wBACf,CAAC,EAAE,CAAC,CAAC,qBAAqB;oBAC5B,CAAC;yBAAM,CAAC;wBACN,QAAQ,GAAG,KAAK,CAAC;oBACnB,CAAC;gBACH,CAAC;qBAAM,CAAC;oBACN,OAAO,IAAI,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;oBACjB,QAAQ,GAAG,IAAI,CAAC;gBAClB,CAAC;qBAAM,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBAC9B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;oBAC5B,OAAO,GAAG,EAAE,CAAC;gBACf,CAAC;qBAAM,CAAC;oBACN,OAAO,IAAI,IAAI,CAAC;gBAClB,CAAC;YACH,CAAC;QACH,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC;IAEF,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QACpC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACjC,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACxC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YACvC,CAAC;YACD,OAAO,MAAW,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;SAAM,CAAC;QACN,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;YACxB,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;YAC/B,MAAM,MAAM,GAA2B,EAAE,CAAC;YAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACvC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;YAChC,CAAC;YACD,OAAO,MAAW,CAAC;QACrB,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAoBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAE5B,IAAY,EAAE,OAAyB;IACvC,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;IAChC,OAAO,YAAY,CAAI,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AACpD,CAAC;AAED,gFAAgF;AAChF,eAAe;AACf,gFAAgF;AAEhF;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAE7B,IAAY;IACZ,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACpD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACvE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC/B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAM,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,0BAA0B,KAAK,GAAG,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CACvE,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC;AAwCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAE3B,IAAY,EAAE,OAAwB;IACtC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,YAAY,GAAG,QAAQ,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;QAE3G,MAAM,CAAC,IAAI,CAAC;YACV,KAAK,EAAE,IAAI;YACX,KAAK,EAAE,YAAY;YACnB,GAAG,OAAO;SACK,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,OAAO,CAAC,MAAM,GAAG,KAAK,UAAU,aAAa,CAE3C,IAAY,EAAE,OAA8B;IAC5C,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEnD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,MAAM,GAAQ,EAAE,CAAC;IACvB,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAI,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;QAChE,MAAM,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,CAAC,KAAK,GAAG,KAAK,UAAU,YAAY,CAEzC,IAAY,EAAE,OAAwB;IACtC,MAAM,KAAK,GAAG,MAAM,eAAe,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;QAC7B,MAAM,OAAO,GAAG,MAAM,sBAAsB,CAAC,QAAQ,CAAC,CAAC;QACvD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF;;;;GAIG;AACH,KAAK,UAAU,eAAe,CAC5B,IAAY,EACZ,OAAwB;IAExB,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,OAAO,CAAC,CAAC;IACpD,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,IAAI,KAAK,CAAC;IAC9C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,YAAY,CAAC,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC;IACvD,KAAK,CAAC,IAAI,EAAE,CAAC;IACb,OAAO,KAAK,CAAC;AACf,CAAC;AAED,gFAAgF;AAChF,+BAA+B;AAC/B,gFAAgF;AAEhF;;;GAGG;AACH,KAAK,UAAU,YAAY,CACzB,GAAW,EACX,UAAoB,EACpB,SAAkB,EAClB,MAAgB;IAEhB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;YAEpF,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;gBACnB,MAAM,UAAU,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;gBAClG,IAAI,UAAU,EAAE,CAAC;oBACf,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACxB,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,SAAS,EAAE,CAAC;gBAC5C,MAAM,YAAY,CAAC,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,sBAAsB,CAAC,GAAG,EAAE,gBAAgB,EAAE,KAAK,CAAC,CAAC;IAC7D,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,KAAK,UAAU,YAAY,CACzB,QAAgB,EAChB,IAAa;IAEb,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IAErC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAmB,CAAC;IACrD,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,SAAS,CAAI,QAAQ,CAAC,CAAC;IACtC,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,OAAO,MAAM,QAAQ,CAAI,QAAQ,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,gBAAgB;IAChB,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACrD,OAAO,YAAY,CAAI,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;AAC/C,CAAC;AAED;;;GAGG;AACH,KAAK,UAAU,sBAAsB,CACnC,QAAgB;IAEhB,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,MAAM,OAAO,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAExD,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC;QAChC,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,OAAO,IAA+B,CAAC;QACzC,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,CAAC;IAClB,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,6DAA6D;QAC7D,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACnE,IAAI,SAAS,EAAE,CAAC;YACd,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,0DAA0D;QAC1D,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;IAED,gBAAgB;IAChB,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjC,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;QAC7D,OAAO,IAA+B,CAAC;IACzC,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,CAAC;AAClB,CAAC;AAED;;;GAGG;AACH,SAAS,kBAAkB,CAAC,QAAgB;IAC1C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;IACzC,MAAM,OAAO,GAAG,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IAC1C,OAAO,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;AACpE,CAAC"}
|