@jiordikengne/velar 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/README.md +123 -0
- package/dist/commands/add.js +85 -0
- package/dist/commands/add.js.map +1 -0
- package/dist/commands/init-handlers.js +138 -0
- package/dist/commands/init-handlers.js.map +1 -0
- package/dist/commands/init-new.js +126 -0
- package/dist/commands/init-new.js.map +1 -0
- package/dist/commands/init-old.js +218 -0
- package/dist/commands/init-old.js.map +1 -0
- package/dist/commands/init.js +125 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/list.js +69 -0
- package/dist/commands/list.js.map +1 -0
- package/dist/config/ConfigManager.js +89 -0
- package/dist/config/ConfigManager.js.map +1 -0
- package/dist/errors/ErrorHandler.js +42 -0
- package/dist/errors/ErrorHandler.js.map +1 -0
- package/dist/errors/errors.js +45 -0
- package/dist/errors/errors.js.map +1 -0
- package/dist/index.js +30 -0
- package/dist/index.js.map +1 -0
- package/dist/registry/blue.css +0 -0
- package/dist/registry/green.css +0 -0
- package/dist/registry/neutral.css +29 -0
- package/dist/registry/orange.css +0 -0
- package/dist/registry/red.css +0 -0
- package/dist/registry/rose.css +0 -0
- package/dist/registry/themes/blue.css +0 -0
- package/dist/registry/themes/green.css +0 -0
- package/dist/registry/themes/neutral.css +29 -0
- package/dist/registry/themes/orange.css +0 -0
- package/dist/registry/themes/red.css +0 -0
- package/dist/registry/themes/rose.css +0 -0
- package/dist/registry/themes/violet.css +0 -0
- package/dist/registry/themes/yellow.css +0 -0
- package/dist/registry/violet.css +0 -0
- package/dist/registry/yellow.css +0 -0
- package/dist/services/AddService.js +98 -0
- package/dist/services/AddService.js.map +1 -0
- package/dist/services/ComponentService.js +167 -0
- package/dist/services/ComponentService.js.map +1 -0
- package/dist/services/FileSystemService.js +51 -0
- package/dist/services/FileSystemService.js.map +1 -0
- package/dist/services/HttpService.js +181 -0
- package/dist/services/HttpService.js.map +1 -0
- package/dist/services/InitService.js +182 -0
- package/dist/services/InitService.js.map +1 -0
- package/dist/services/ListService.js +52 -0
- package/dist/services/ListService.js.map +1 -0
- package/dist/services/RegistryService.js +85 -0
- package/dist/services/RegistryService.js.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/interfaces.js +2 -0
- package/dist/types/interfaces.js.map +1 -0
- package/dist/types/meta.js +2 -0
- package/dist/types/meta.js.map +1 -0
- package/dist/types/registry.js +2 -0
- package/dist/types/registry.js.map +1 -0
- package/dist/utils/alpine-installer.js +46 -0
- package/dist/utils/alpine-installer.js.map +1 -0
- package/dist/utils/config.js +21 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/css.js +53 -0
- package/dist/utils/css.js.map +1 -0
- package/dist/utils/deps.js +24 -0
- package/dist/utils/deps.js.map +1 -0
- package/dist/utils/environment.js +8 -0
- package/dist/utils/environment.js.map +1 -0
- package/dist/utils/errors.js +21 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/filesystem.js +14 -0
- package/dist/utils/filesystem.js.map +1 -0
- package/dist/utils/js.js +63 -0
- package/dist/utils/js.js.map +1 -0
- package/dist/utils/laravel.js +9 -0
- package/dist/utils/laravel.js.map +1 -0
- package/dist/utils/logger.js +47 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/package-manager.js +23 -0
- package/dist/utils/package-manager.js.map +1 -0
- package/dist/utils/registry.js +17 -0
- package/dist/utils/registry.js.map +1 -0
- package/dist/utils/remote-registry.js +162 -0
- package/dist/utils/remote-registry.js.map +1 -0
- package/dist/utils/requirements.js +75 -0
- package/dist/utils/requirements.js.map +1 -0
- package/dist/utils/spinner.js +40 -0
- package/dist/utils/spinner.js.map +1 -0
- package/dist/utils/tailwind.js +31 -0
- package/dist/utils/tailwind.js.map +1 -0
- package/dist/utils/theme.js +32 -0
- package/dist/utils/theme.js.map +1 -0
- package/dist/utils/type-conversion.js +2 -0
- package/dist/utils/type-conversion.js.map +1 -0
- package/package.json +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,mBAAmB,MAAM,oBAAoB,CAAC;AACrD,OAAO,kBAAkB,MAAM,mBAAmB,CAAC;AACnD,OAAO,mBAAmB,MAAM,oBAAoB,CAAC;AAErD;;GAEG;AACH,SAAS,YAAY;IACnB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAC,CAAC;IACrE,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAC9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,yDAAyD,CAAC;KACtE,OAAO,CAAC,OAAO,CAAC;KAChB,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IACtB,YAAY,EAAE,CAAC;AACjB,CAAC,CAAC,CAAC;AAEL,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,kBAAkB,CAAC,OAAO,CAAC,CAAC;AAC5B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7B,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--radius: 0.625rem;
|
|
3
|
+
|
|
4
|
+
--background: oklch(1 0 0);
|
|
5
|
+
--foreground: oklch(0.145 0 0);
|
|
6
|
+
|
|
7
|
+
--primary: oklch(0.205 0 0);
|
|
8
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
9
|
+
|
|
10
|
+
--secondary: oklch(0.97 0 0);
|
|
11
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
12
|
+
|
|
13
|
+
--border: oklch(0.922 0 0);
|
|
14
|
+
--ring: oklch(0.708 0 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dark {
|
|
18
|
+
--background: oklch(0.145 0 0);
|
|
19
|
+
--foreground: oklch(0.985 0 0);
|
|
20
|
+
|
|
21
|
+
--primary: oklch(0.922 0 0);
|
|
22
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
23
|
+
|
|
24
|
+
--secondary: oklch(0.269 0 0);
|
|
25
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
26
|
+
|
|
27
|
+
--border: oklch(1 0 0 / 10%);
|
|
28
|
+
--ring: oklch(0.439 0 0);
|
|
29
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--radius: 0.625rem;
|
|
3
|
+
|
|
4
|
+
--background: oklch(1 0 0);
|
|
5
|
+
--foreground: oklch(0.145 0 0);
|
|
6
|
+
|
|
7
|
+
--primary: oklch(0.205 0 0);
|
|
8
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
9
|
+
|
|
10
|
+
--secondary: oklch(0.97 0 0);
|
|
11
|
+
--secondary-foreground: oklch(0.205 0 0);
|
|
12
|
+
|
|
13
|
+
--border: oklch(0.922 0 0);
|
|
14
|
+
--ring: oklch(0.708 0 0);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.dark {
|
|
18
|
+
--background: oklch(0.145 0 0);
|
|
19
|
+
--foreground: oklch(0.985 0 0);
|
|
20
|
+
|
|
21
|
+
--primary: oklch(0.922 0 0);
|
|
22
|
+
--primary-foreground: oklch(0.205 0 0);
|
|
23
|
+
|
|
24
|
+
--secondary: oklch(0.269 0 0);
|
|
25
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
26
|
+
|
|
27
|
+
--border: oklch(1 0 0 / 10%);
|
|
28
|
+
--ring: oklch(0.439 0 0);
|
|
29
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { ComponentService } from "./ComponentService.js";
|
|
2
|
+
import { FileSystemService } from "./FileSystemService.js";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
/**
|
|
5
|
+
* Service for handling component addition operations
|
|
6
|
+
*/
|
|
7
|
+
export class AddService {
|
|
8
|
+
registryService;
|
|
9
|
+
configManager;
|
|
10
|
+
componentService;
|
|
11
|
+
/**
|
|
12
|
+
* Create a new AddService instance
|
|
13
|
+
* @param registryService - Service for registry operations
|
|
14
|
+
* @param configManager - Service for configuration management
|
|
15
|
+
* @param componentService - Optional component service (creates new one if not provided)
|
|
16
|
+
*/
|
|
17
|
+
constructor(registryService, configManager, componentService) {
|
|
18
|
+
this.registryService = registryService;
|
|
19
|
+
this.configManager = configManager;
|
|
20
|
+
// ComponentService will be created if not provided
|
|
21
|
+
// This allows for dependency injection in tests
|
|
22
|
+
this.componentService =
|
|
23
|
+
componentService ??
|
|
24
|
+
new ComponentService(registryService, new FileSystemService(), configManager);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validate that Velar is initialized
|
|
28
|
+
* @throws Error if not initialized
|
|
29
|
+
*/
|
|
30
|
+
validateInitialization() {
|
|
31
|
+
if (!this.configManager.validate()) {
|
|
32
|
+
throw new Error("Velar is not initialized");
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validate that components exist in the registry
|
|
37
|
+
* @param componentNames - Names of components to validate
|
|
38
|
+
* @param registry - Registry data
|
|
39
|
+
* @throws Error if any component is not found
|
|
40
|
+
*/
|
|
41
|
+
validateComponents(componentNames, registry) {
|
|
42
|
+
for (const componentName of componentNames) {
|
|
43
|
+
const found = registry.components.find((c) => c.name === componentName);
|
|
44
|
+
if (!found) {
|
|
45
|
+
throw new Error(`Component "${componentName}" not found`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Get available components from registry
|
|
51
|
+
* @returns Promise resolving to registry data
|
|
52
|
+
* @throws NetworkError if fetch fails
|
|
53
|
+
*/
|
|
54
|
+
async getAvailableComponents() {
|
|
55
|
+
return await this.registryService.fetchRegistry();
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Add components to the project
|
|
59
|
+
* @param componentNames - Names of components to add
|
|
60
|
+
* @returns Promise resolving to result of the operation
|
|
61
|
+
*/
|
|
62
|
+
async addComponents(componentNames) {
|
|
63
|
+
return await this.componentService.addComponents(componentNames);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Display the results of adding components
|
|
67
|
+
* @param result - Result of the add operation
|
|
68
|
+
*/
|
|
69
|
+
displayResults(result) {
|
|
70
|
+
result.added.forEach((name) => logger.success(`Added ${name}`));
|
|
71
|
+
result.skipped.forEach((name) => logger.warning(`Skipped ${name}`));
|
|
72
|
+
result.failed.forEach(({ name, error }) => logger.error(`Failed to add ${name}: ${error}`));
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Display next steps after adding components
|
|
76
|
+
* @param result - Result of the add operation
|
|
77
|
+
*/
|
|
78
|
+
displayNextSteps(result) {
|
|
79
|
+
if (result.added.length === 0) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
console.log("\nNext steps:");
|
|
83
|
+
console.log(" Use <x-ui.COMPONENT> in your Blade views");
|
|
84
|
+
// Check if JS files were added but not auto-imported
|
|
85
|
+
const jsFiles = result.added.filter((name) => name.endsWith(".js"));
|
|
86
|
+
const hasJsEntry = this.configManager.validate() && this.configManager.getJsEntryPath();
|
|
87
|
+
if (jsFiles.length > 0 && !hasJsEntry) {
|
|
88
|
+
console.log(" Import JS files in your app.js:");
|
|
89
|
+
jsFiles.forEach((file) => {
|
|
90
|
+
const fileName = file.split("/")[1];
|
|
91
|
+
if (fileName) {
|
|
92
|
+
console.log(` import './ui/${fileName}'`);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=AddService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AddService.js","sourceRoot":"","sources":["../../src/services/AddService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import * as p from "@clack/prompts";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import { logger } from "../utils/logger.js";
|
|
4
|
+
import { FileSystemService } from "./FileSystemService.js";
|
|
5
|
+
import { injectComponentJs } from "../utils/js.js";
|
|
6
|
+
/**
|
|
7
|
+
* Service for managing component operations
|
|
8
|
+
*/
|
|
9
|
+
export class ComponentService {
|
|
10
|
+
registryService;
|
|
11
|
+
configManager;
|
|
12
|
+
fileSystem;
|
|
13
|
+
/**
|
|
14
|
+
* Create a new ComponentService instance
|
|
15
|
+
* @param registryService - Service for registry operations
|
|
16
|
+
* @param fileSystem - Optional file system service (creates new one if not provided)
|
|
17
|
+
* @param configManager - Service for configuration management
|
|
18
|
+
*/
|
|
19
|
+
constructor(registryService, fileSystem, configManager) {
|
|
20
|
+
this.registryService = registryService;
|
|
21
|
+
this.configManager = configManager;
|
|
22
|
+
this.fileSystem = fileSystem ?? new FileSystemService();
|
|
23
|
+
if (!this.configManager) {
|
|
24
|
+
throw new Error("ConfigManager is required");
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Add multiple components to the project
|
|
29
|
+
* @param componentNames - Array of component names to add
|
|
30
|
+
* @returns Promise resolving to result of the operation
|
|
31
|
+
*/
|
|
32
|
+
async addComponents(componentNames) {
|
|
33
|
+
const result = {
|
|
34
|
+
added: [],
|
|
35
|
+
skipped: [],
|
|
36
|
+
failed: [],
|
|
37
|
+
};
|
|
38
|
+
for (const componentName of componentNames) {
|
|
39
|
+
try {
|
|
40
|
+
const componentResult = await this.addComponent(componentName);
|
|
41
|
+
result.added.push(...componentResult.added);
|
|
42
|
+
result.skipped.push(...componentResult.skipped);
|
|
43
|
+
result.failed.push(...componentResult.failed);
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
result.failed.push({
|
|
47
|
+
name: componentName,
|
|
48
|
+
error: error.message,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Add a single component to the project
|
|
56
|
+
* @param componentName - Name of the component to add
|
|
57
|
+
* @returns Promise resolving to result of the operation
|
|
58
|
+
* @throws Error if component fetch fails
|
|
59
|
+
*/
|
|
60
|
+
async addComponent(componentName) {
|
|
61
|
+
const result = {
|
|
62
|
+
added: [],
|
|
63
|
+
skipped: [],
|
|
64
|
+
failed: [],
|
|
65
|
+
};
|
|
66
|
+
// Fetch component metadata
|
|
67
|
+
const component = await this.registryService.fetchComponent(componentName);
|
|
68
|
+
// Resolve dependencies
|
|
69
|
+
const componentsToAdd = await this.registryService.resolveDependencies(component);
|
|
70
|
+
// Get components path
|
|
71
|
+
const componentsPath = this.configManager.getComponentsPath();
|
|
72
|
+
for (const comp of componentsToAdd) {
|
|
73
|
+
// Process all files (blade, js, css)
|
|
74
|
+
for (const file of comp.files) {
|
|
75
|
+
const content = await this.registryService.fetchFile(comp.name, file.path);
|
|
76
|
+
// Determine destination based on file type
|
|
77
|
+
const dest = this.getDestinationPath(comp, file, componentsPath);
|
|
78
|
+
// Check if file exists and handle conflict
|
|
79
|
+
if (await this.fileSystem.fileExists(dest)) {
|
|
80
|
+
const action = await this.handleFileConflict(file.path);
|
|
81
|
+
if (action === "skip") {
|
|
82
|
+
result.skipped.push(`${comp.name}/${file.path}`);
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
else if (action === "cancel") {
|
|
86
|
+
logger.error("Cancelled.");
|
|
87
|
+
process.exit(0);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Write the file
|
|
91
|
+
try {
|
|
92
|
+
await this.fileSystem.writeFile(dest, content);
|
|
93
|
+
result.added.push(`${comp.name}/${file.path}`);
|
|
94
|
+
// Handle JS auto-import
|
|
95
|
+
if (file.type === "js") {
|
|
96
|
+
await this.autoImportJs(comp.name);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
result.failed.push({
|
|
101
|
+
name: `${comp.name}/${file.path}`,
|
|
102
|
+
error: error.message,
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return result;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Automatically import component JS into the main JS entry
|
|
111
|
+
* @param componentName - Name of the component
|
|
112
|
+
*/
|
|
113
|
+
async autoImportJs(componentName) {
|
|
114
|
+
try {
|
|
115
|
+
const jsEntry = this.configManager?.getJsEntryPath();
|
|
116
|
+
if (!jsEntry || !(await this.fileSystem.fileExists(jsEntry))) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
const importPath = `./ui/${componentName}`;
|
|
120
|
+
injectComponentJs(jsEntry, componentName, importPath);
|
|
121
|
+
logger.success(`Auto-imported ${componentName} into ${jsEntry}`);
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
logger.warning(`Failed to auto-import JS for ${componentName}: ${error.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get the destination path for a component file
|
|
129
|
+
* @param component - Component metadata
|
|
130
|
+
* @param file - File metadata
|
|
131
|
+
* @param componentsPath - Base components path
|
|
132
|
+
* @returns Destination file path
|
|
133
|
+
*/
|
|
134
|
+
getDestinationPath(component, file, componentsPath) {
|
|
135
|
+
switch (file.type) {
|
|
136
|
+
case "blade":
|
|
137
|
+
return path.join(componentsPath, `${component.name}.blade.php`);
|
|
138
|
+
case "js":
|
|
139
|
+
return path.join("resources/js/ui", `${component.name}.js`);
|
|
140
|
+
case "css":
|
|
141
|
+
return path.join("resources/css/components", `${component.name}.css`);
|
|
142
|
+
default:
|
|
143
|
+
return path.join(componentsPath, file.path);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Handle file conflict by prompting user
|
|
148
|
+
* @param filePath - Path of the conflicting file
|
|
149
|
+
* @returns Promise resolving to user action ("skip", "overwrite", or "cancel")
|
|
150
|
+
*/
|
|
151
|
+
async handleFileConflict(filePath) {
|
|
152
|
+
const action = await p.select({
|
|
153
|
+
message: `File "${filePath}" already exists. What do you want to do?`,
|
|
154
|
+
options: [
|
|
155
|
+
{ label: "Skip", value: "skip" },
|
|
156
|
+
{ label: "Overwrite", value: "overwrite" },
|
|
157
|
+
{ label: "Cancel", value: "cancel" },
|
|
158
|
+
],
|
|
159
|
+
initialValue: "skip",
|
|
160
|
+
});
|
|
161
|
+
if (p.isCancel(action)) {
|
|
162
|
+
return "cancel";
|
|
163
|
+
}
|
|
164
|
+
return action;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=ComponentService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ComponentService.js","sourceRoot":"","sources":["../../src/services/ComponentService.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { promises as fs } from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Service for file system operations
|
|
5
|
+
*/
|
|
6
|
+
export class FileSystemService {
|
|
7
|
+
/**
|
|
8
|
+
* Check if a file exists
|
|
9
|
+
* @param filePath - Path to check
|
|
10
|
+
* @returns Promise resolving to true if file exists
|
|
11
|
+
*/
|
|
12
|
+
async fileExists(filePath) {
|
|
13
|
+
try {
|
|
14
|
+
await fs.access(filePath);
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Write content to a file, creating directories if necessary
|
|
23
|
+
* @param filePath - Path to write to
|
|
24
|
+
* @param content - Content to write
|
|
25
|
+
* @returns Promise that resolves when file is written
|
|
26
|
+
* @throws Error if write fails
|
|
27
|
+
*/
|
|
28
|
+
async writeFile(filePath, content) {
|
|
29
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
30
|
+
await fs.writeFile(filePath, content, "utf-8");
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read content from a file
|
|
34
|
+
* @param filePath - Path to read from
|
|
35
|
+
* @returns Promise resolving to file content
|
|
36
|
+
* @throws Error if file doesn't exist or read fails
|
|
37
|
+
*/
|
|
38
|
+
async readFile(filePath) {
|
|
39
|
+
return await fs.readFile(filePath, "utf-8");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Ensure a directory exists, creating it if necessary
|
|
43
|
+
* @param dirPath - Directory path
|
|
44
|
+
* @returns Promise that resolves when directory is ensured
|
|
45
|
+
* @throws Error if directory creation fails
|
|
46
|
+
*/
|
|
47
|
+
async ensureDir(dirPath) {
|
|
48
|
+
await fs.mkdir(dirPath, { recursive: true });
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=FileSystemService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FileSystemService.js","sourceRoot":"","sources":["../../src/services/FileSystemService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB;;GAEG;AACH,MAAM,OAAO,iBAAiB;IAC5B;;;;OAIG;IACH,KAAK,CAAC,UAAU,CAAC,QAAgB;QAC/B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC1B,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,OAAe;QAC/C,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,QAAgB;QAC7B,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,SAAS,CAAC,OAAe;QAC7B,MAAM,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;CACF"}
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { NetworkError } from "../errors/errors.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default retry options
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_RETRY_OPTIONS = {
|
|
6
|
+
maxRetries: 3,
|
|
7
|
+
initialDelay: 1000,
|
|
8
|
+
backoffFactor: 2,
|
|
9
|
+
maxDelay: 10000,
|
|
10
|
+
retryableStatusCodes: [408, 429, 500, 502, 503, 504],
|
|
11
|
+
timeout: 30000,
|
|
12
|
+
headers: {},
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Sleep utility for retry delays
|
|
16
|
+
* @param ms - Milliseconds to sleep
|
|
17
|
+
*/
|
|
18
|
+
function sleep(ms) {
|
|
19
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Calculate delay for retry attempt with exponential backoff
|
|
23
|
+
* @param attempt - Current attempt number (0-indexed)
|
|
24
|
+
* @param initialDelay - Initial delay in milliseconds
|
|
25
|
+
* @param backoffFactor - Factor to multiply delay by each attempt
|
|
26
|
+
* @param maxDelay - Maximum delay in milliseconds
|
|
27
|
+
* @returns Delay in milliseconds
|
|
28
|
+
*/
|
|
29
|
+
function calculateDelay(attempt, initialDelay, backoffFactor, maxDelay) {
|
|
30
|
+
const delay = initialDelay * Math.pow(backoffFactor, attempt);
|
|
31
|
+
return Math.min(delay, maxDelay);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if a status code is retryable
|
|
35
|
+
* @param status - HTTP status code
|
|
36
|
+
* @param retryableStatusCodes - List of retryable status codes
|
|
37
|
+
* @returns True if status code is retryable
|
|
38
|
+
*/
|
|
39
|
+
function isRetryableStatus(status, retryableStatusCodes) {
|
|
40
|
+
return retryableStatusCodes.includes(status);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Create a fetch request with timeout
|
|
44
|
+
* @param url - URL to fetch
|
|
45
|
+
* @param options - Fetch options including timeout
|
|
46
|
+
* @returns Promise resolving to Response
|
|
47
|
+
*/
|
|
48
|
+
async function fetchWithTimeout(url, options) {
|
|
49
|
+
const { timeout = DEFAULT_RETRY_OPTIONS.timeout, headers = {} } = options;
|
|
50
|
+
const controller = new AbortController();
|
|
51
|
+
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
52
|
+
try {
|
|
53
|
+
const response = await fetch(url, {
|
|
54
|
+
signal: controller.signal,
|
|
55
|
+
headers: {
|
|
56
|
+
"User-Agent": "Velar-CLI",
|
|
57
|
+
...headers,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
return response;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
64
|
+
throw new NetworkError(`Request timeout after ${timeout}ms for ${url}`, error);
|
|
65
|
+
}
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
finally {
|
|
69
|
+
clearTimeout(timeoutId);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* HTTP service with retry logic and timeout support
|
|
74
|
+
*/
|
|
75
|
+
export class HttpService {
|
|
76
|
+
/**
|
|
77
|
+
* Fetch a URL with retry logic and timeout
|
|
78
|
+
* @param url - URL to fetch
|
|
79
|
+
* @param options - Fetch options including retry configuration
|
|
80
|
+
* @returns Promise resolving to Response
|
|
81
|
+
* @throws NetworkError if all retries fail
|
|
82
|
+
*/
|
|
83
|
+
async fetch(url, options = {}) {
|
|
84
|
+
const retryOptions = {
|
|
85
|
+
maxRetries: options.maxRetries ?? DEFAULT_RETRY_OPTIONS.maxRetries,
|
|
86
|
+
initialDelay: options.initialDelay ?? DEFAULT_RETRY_OPTIONS.initialDelay,
|
|
87
|
+
backoffFactor: options.backoffFactor ?? DEFAULT_RETRY_OPTIONS.backoffFactor,
|
|
88
|
+
maxDelay: options.maxDelay ?? DEFAULT_RETRY_OPTIONS.maxDelay,
|
|
89
|
+
retryableStatusCodes: options.retryableStatusCodes ??
|
|
90
|
+
DEFAULT_RETRY_OPTIONS.retryableStatusCodes,
|
|
91
|
+
timeout: options.timeout ?? DEFAULT_RETRY_OPTIONS.timeout,
|
|
92
|
+
headers: options.headers ?? DEFAULT_RETRY_OPTIONS.headers,
|
|
93
|
+
};
|
|
94
|
+
let lastError = null;
|
|
95
|
+
for (let attempt = 0; attempt <= retryOptions.maxRetries; attempt++) {
|
|
96
|
+
try {
|
|
97
|
+
const response = await fetchWithTimeout(url, {
|
|
98
|
+
...options,
|
|
99
|
+
timeout: retryOptions.timeout,
|
|
100
|
+
headers: retryOptions.headers,
|
|
101
|
+
});
|
|
102
|
+
// If response is successful or not retryable, return it
|
|
103
|
+
if (response.ok ||
|
|
104
|
+
!isRetryableStatus(response.status, retryOptions.retryableStatusCodes)) {
|
|
105
|
+
return response;
|
|
106
|
+
}
|
|
107
|
+
console.log("Attempt: ", attempt);
|
|
108
|
+
// If this is the last attempt, throw error
|
|
109
|
+
if (attempt === retryOptions.maxRetries) {
|
|
110
|
+
throw new NetworkError(`Request failed after ${retryOptions.maxRetries + 1} attempts: ${response.status} ${response.statusText}`);
|
|
111
|
+
}
|
|
112
|
+
// Calculate delay and wait before retry
|
|
113
|
+
const delay = calculateDelay(attempt, retryOptions.initialDelay, retryOptions.backoffFactor, retryOptions.maxDelay);
|
|
114
|
+
await sleep(delay);
|
|
115
|
+
}
|
|
116
|
+
catch (error) {
|
|
117
|
+
lastError = error;
|
|
118
|
+
// Don't retry on certain errors
|
|
119
|
+
if (error instanceof NetworkError &&
|
|
120
|
+
error.message.includes("timeout")) {
|
|
121
|
+
if (attempt === retryOptions.maxRetries) {
|
|
122
|
+
throw error;
|
|
123
|
+
}
|
|
124
|
+
const delay = calculateDelay(attempt, retryOptions.initialDelay, retryOptions.backoffFactor, retryOptions.maxDelay);
|
|
125
|
+
await sleep(delay);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
// If this is the last attempt, throw error
|
|
129
|
+
if (attempt === retryOptions.maxRetries) {
|
|
130
|
+
if (lastError instanceof NetworkError) {
|
|
131
|
+
throw lastError;
|
|
132
|
+
}
|
|
133
|
+
throw new NetworkError(`Request failed after ${retryOptions.maxRetries + 1} attempts: ${lastError.message}`, lastError);
|
|
134
|
+
}
|
|
135
|
+
// Calculate delay and wait before retry
|
|
136
|
+
const delay = calculateDelay(attempt, retryOptions.initialDelay, retryOptions.backoffFactor, retryOptions.maxDelay);
|
|
137
|
+
await sleep(delay);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
throw new NetworkError(`Request failed after ${retryOptions.maxRetries + 1} attempts: ${lastError?.message ?? "Unknown error"}`, lastError ?? undefined);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Fetch JSON from a URL with retry logic
|
|
144
|
+
* @param url - URL to fetch
|
|
145
|
+
* @param options - Fetch options
|
|
146
|
+
* @returns Promise resolving to parsed JSON
|
|
147
|
+
* @throws NetworkError if fetch or parsing fails
|
|
148
|
+
*/
|
|
149
|
+
async fetchJson(url, options) {
|
|
150
|
+
const response = await this.fetch(url, options);
|
|
151
|
+
if (!response.ok) {
|
|
152
|
+
throw new NetworkError(`Failed to fetch JSON from ${url}: ${response.status} ${response.statusText}`);
|
|
153
|
+
}
|
|
154
|
+
try {
|
|
155
|
+
return (await response.json());
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
throw new NetworkError(`Failed to parse JSON from ${url}: ${error.message}`, error);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Fetch text from a URL with retry logic
|
|
163
|
+
* @param url - URL to fetch
|
|
164
|
+
* @param options - Fetch options
|
|
165
|
+
* @returns Promise resolving to text content
|
|
166
|
+
* @throws NetworkError if fetch fails
|
|
167
|
+
*/
|
|
168
|
+
async fetchText(url, options) {
|
|
169
|
+
const response = await this.fetch(url, options);
|
|
170
|
+
if (!response.ok) {
|
|
171
|
+
throw new NetworkError(`Failed to fetch text from ${url}: ${response.status} ${response.statusText}`);
|
|
172
|
+
}
|
|
173
|
+
try {
|
|
174
|
+
return await response.text();
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
throw new NetworkError(`Failed to read text from ${url}: ${error.message}`, error);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=HttpService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"HttpService.js","sourceRoot":"","sources":["../../src/services/HttpService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAGnD;;GAEG;AACH,MAAM,qBAAqB,GAA2B;IACpD,UAAU,EAAE,CAAC;IACb,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE,CAAC;IAChB,QAAQ,EAAE,KAAK;IACf,oBAAoB,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;IACpD,OAAO,EAAE,KAAK;IACd,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF;;;GAGG;AACH,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,cAAc,CACrB,OAAe,EACf,YAAoB,EACpB,aAAqB,EACrB,QAAgB;IAEhB,MAAM,KAAK,GAAG,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;IAC9D,OAAO,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CACxB,MAAc,EACd,oBAAuC;IAEvC,OAAO,oBAAoB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;AAC/C,CAAC;AAED;;;;;GAKG;AACH,KAAK,UAAU,gBAAgB,CAC7B,GAAW,EACX,OAAqB;IAErB,MAAM,EAAE,OAAO,GAAG,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAE1E,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,MAAM,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;IAEhE,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE;gBACP,YAAY,EAAE,WAAW;gBACzB,GAAG,OAAO;aACX;SACF,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAC1D,MAAM,IAAI,YAAY,CACpB,yBAAyB,OAAO,UAAU,GAAG,EAAE,EAC/C,KAAK,CACN,CAAC;QACJ,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,SAAS,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,WAAW;IACtB;;;;;;OAMG;IACH,KAAK,CAAC,KAAK,CAAC,GAAW,EAAE,UAAwB,EAAE;QACjD,MAAM,YAAY,GAAG;YACnB,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,qBAAqB,CAAC,UAAU;YAClE,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,qBAAqB,CAAC,YAAY;YACxE,aAAa,EACX,OAAO,CAAC,aAAa,IAAI,qBAAqB,CAAC,aAAa;YAC9D,QAAQ,EAAE,OAAO,CAAC,QAAQ,IAAI,qBAAqB,CAAC,QAAQ;YAC5D,oBAAoB,EAClB,OAAO,CAAC,oBAAoB;gBAC5B,qBAAqB,CAAC,oBAAoB;YAC5C,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,qBAAqB,CAAC,OAAO;YACzD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,qBAAqB,CAAC,OAAO;SAC1D,CAAC;QAEF,IAAI,SAAS,GAAiB,IAAI,CAAC;QAEnC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,YAAY,CAAC,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;YACpE,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,GAAG,EAAE;oBAC3C,GAAG,OAAO;oBACV,OAAO,EAAE,YAAY,CAAC,OAAO;oBAC7B,OAAO,EAAE,YAAY,CAAC,OAAO;iBAC9B,CAAC,CAAC;gBAEH,wDAAwD;gBACxD,IACE,QAAQ,CAAC,EAAE;oBACX,CAAC,iBAAiB,CAAC,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC,oBAAoB,CAAC,EACtE,CAAC;oBACD,OAAO,QAAQ,CAAC;gBAClB,CAAC;gBACD,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;gBAClC,2CAA2C;gBAC3C,IAAI,OAAO,KAAK,YAAY,CAAC,UAAU,EAAE,CAAC;oBACxC,MAAM,IAAI,YAAY,CACpB,wBAAwB,YAAY,CAAC,UAAU,GAAG,CAAC,cAAc,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC1G,CAAC;gBACJ,CAAC;gBAED,wCAAwC;gBACxC,MAAM,KAAK,GAAG,cAAc,CAC1B,OAAO,EACP,YAAY,CAAC,YAAY,EACzB,YAAY,CAAC,aAAa,EAC1B,YAAY,CAAC,QAAQ,CACtB,CAAC;gBACF,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,SAAS,GAAG,KAAc,CAAC;gBAE3B,gCAAgC;gBAChC,IACE,KAAK,YAAY,YAAY;oBAC7B,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,EACjC,CAAC;oBACD,IAAI,OAAO,KAAK,YAAY,CAAC,UAAU,EAAE,CAAC;wBACxC,MAAM,KAAK,CAAC;oBACd,CAAC;oBACD,MAAM,KAAK,GAAG,cAAc,CAC1B,OAAO,EACP,YAAY,CAAC,YAAY,EACzB,YAAY,CAAC,aAAa,EAC1B,YAAY,CAAC,QAAQ,CACtB,CAAC;oBACF,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;oBACnB,SAAS;gBACX,CAAC;gBAED,2CAA2C;gBAC3C,IAAI,OAAO,KAAK,YAAY,CAAC,UAAU,EAAE,CAAC;oBACxC,IAAI,SAAS,YAAY,YAAY,EAAE,CAAC;wBACtC,MAAM,SAAS,CAAC;oBAClB,CAAC;oBACD,MAAM,IAAI,YAAY,CACpB,wBAAwB,YAAY,CAAC,UAAU,GAAG,CAAC,cAAc,SAAS,CAAC,OAAO,EAAE,EACpF,SAAS,CACV,CAAC;gBACJ,CAAC;gBAED,wCAAwC;gBACxC,MAAM,KAAK,GAAG,cAAc,CAC1B,OAAO,EACP,YAAY,CAAC,YAAY,EACzB,YAAY,CAAC,aAAa,EAC1B,YAAY,CAAC,QAAQ,CACtB,CAAC;gBACF,MAAM,KAAK,CAAC,KAAK,CAAC,CAAC;YACrB,CAAC;QACH,CAAC;QAED,MAAM,IAAI,YAAY,CACpB,wBAAwB,YAAY,CAAC,UAAU,GAAG,CAAC,cAAc,SAAS,EAAE,OAAO,IAAI,eAAe,EAAE,EACxG,SAAS,IAAI,SAAS,CACvB,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAI,GAAW,EAAE,OAAsB;QACpD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEhD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,YAAY,CACpB,6BAA6B,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC9E,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAM,CAAC;QACtC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,YAAY,CACpB,6BAA6B,GAAG,KAAM,KAAe,CAAC,OAAO,EAAE,EAC/D,KAAc,CACf,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,SAAS,CAAC,GAAW,EAAE,OAAsB;QACjD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEhD,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,YAAY,CACpB,6BAA6B,GAAG,KAAK,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CAC9E,CAAC;QACJ,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,YAAY,CACpB,4BAA4B,GAAG,KAAM,KAAe,CAAC,OAAO,EAAE,EAC9D,KAAc,CACf,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|