clovie 0.1.11 ā 0.1.13
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/bin/cli.js +95 -126
- package/dist/LiveReload-CGbacq3U.js +95 -0
- package/dist/LiveReload-CGbacq3U.js.map +1 -0
- package/dist/Server-B7CJgUcU.js +375 -0
- package/dist/Server-B7CJgUcU.js.map +1 -0
- package/dist/cjs/LiveReload-B2laUnHe.cjs +75 -0
- package/dist/cjs/LiveReload-B2laUnHe.cjs.map +1 -0
- package/dist/cjs/Server-BUMt6MLA.cjs +351 -0
- package/dist/cjs/Server-BUMt6MLA.cjs.map +1 -0
- package/dist/cjs/createClovie-CHAONNH5.cjs +5211 -0
- package/dist/cjs/createClovie-CHAONNH5.cjs.map +1 -0
- package/dist/cjs/index.cjs +8 -0
- package/dist/cjs/index.cjs.map +1 -0
- package/dist/{index.cjs ā createClovie-1_zYoNTN.js} +1907 -1329
- package/dist/createClovie-1_zYoNTN.js.map +1 -0
- package/dist/index.js +13 -4652
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
- package/dist/index.cjs.map +0 -1
package/bin/cli.js
CHANGED
|
@@ -131,14 +131,13 @@ const options = commandLineArgs(optionDefinitions, { argv });
|
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
|
|
134
|
-
// Handle
|
|
134
|
+
// Handle legacy command mappings
|
|
135
135
|
if (mainOptions.command === 'watch') {
|
|
136
|
-
|
|
136
|
+
mainOptions.command = 'dev'; // Map watch to dev
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
// Handle server command
|
|
140
139
|
if (mainOptions.command === 'server') {
|
|
141
|
-
|
|
140
|
+
mainOptions.command = 'serve'; // Map server to serve
|
|
142
141
|
}
|
|
143
142
|
|
|
144
143
|
// Config path
|
|
@@ -147,136 +146,106 @@ const configPath = path.resolve(process.cwd(), options.config);
|
|
|
147
146
|
// Main function
|
|
148
147
|
async function main() {
|
|
149
148
|
try {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
149
|
+
const command = mainOptions.command || 'dev'; // Default to dev
|
|
150
|
+
console.log(`š Starting Clovie ${command}...`);
|
|
151
|
+
|
|
152
|
+
// Step 1: Load config file (with fallback to default)
|
|
153
|
+
const config = await loadConfig(options.config);
|
|
154
|
+
|
|
155
|
+
// Step 2: Determine mode based on command
|
|
156
|
+
const mode = determineMode(command, config);
|
|
157
|
+
|
|
158
|
+
// Step 3: Create Clovie instance with explicit mode
|
|
159
|
+
console.log('āļø Creating Clovie instance...');
|
|
160
|
+
const clovie = await createClovie({
|
|
161
|
+
...config,
|
|
162
|
+
configPath: configPath,
|
|
163
|
+
mode: mode
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
// Step 4: Execute specific command
|
|
167
|
+
await executeCommand(clovie, command, options);
|
|
165
168
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
+
} catch (err) {
|
|
170
|
+
console.error('ā Error:', err.message || err);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Load configuration with fallback
|
|
176
|
+
async function loadConfig(configPath) {
|
|
177
|
+
try {
|
|
178
|
+
const configModule = await import(configPath);
|
|
179
|
+
const config = configModule.default || configModule;
|
|
180
|
+
console.log(`š Using config: ${options.config}`);
|
|
181
|
+
return config;
|
|
182
|
+
} catch (err) {
|
|
183
|
+
if (err.code === 'ERR_MODULE_NOT_FOUND') {
|
|
184
|
+
// Use default config if clovie.config.js not found
|
|
185
|
+
const defaultConfigModule = await import('../config/clovie.config.js');
|
|
186
|
+
const config = defaultConfigModule.default;
|
|
187
|
+
console.log('š Using default Clovie configuration');
|
|
188
|
+
return config;
|
|
189
|
+
} else {
|
|
190
|
+
throw err;
|
|
169
191
|
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
170
194
|
|
|
171
|
-
|
|
172
|
-
|
|
195
|
+
// Determine mode based on command and config
|
|
196
|
+
function determineMode(command, config) {
|
|
197
|
+
// If config explicitly sets mode, use it unless overridden by command
|
|
198
|
+
if (config.mode && !['build', 'serve', 'dev', 'watch'].includes(command)) {
|
|
199
|
+
return config.mode;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Command-based mode determination
|
|
203
|
+
switch (command) {
|
|
204
|
+
case 'build':
|
|
205
|
+
return 'production';
|
|
206
|
+
case 'serve':
|
|
207
|
+
return 'production';
|
|
208
|
+
case 'dev':
|
|
209
|
+
case 'watch':
|
|
210
|
+
return 'development';
|
|
211
|
+
default:
|
|
212
|
+
return 'development';
|
|
213
|
+
}
|
|
214
|
+
}
|
|
173
215
|
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (typeof config.data === 'function') {
|
|
183
|
-
loadedData = await config.data();
|
|
184
|
-
} else if (typeof config.data === 'object') {
|
|
185
|
-
loadedData = config.data;
|
|
186
|
-
}
|
|
187
|
-
clovie.state.load(loadedData);
|
|
188
|
-
console.log(` Loaded ${Object.keys(loadedData).length} data sources into state`);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// Start server
|
|
192
|
-
clovie.server.start();
|
|
193
|
-
|
|
194
|
-
// Keep the process running
|
|
195
|
-
process.on('SIGINT', () => {
|
|
196
|
-
console.log('\nš Stopping server...');
|
|
197
|
-
clovie.server.stop();
|
|
198
|
-
process.exit(0);
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
} else if (options.watch) {
|
|
202
|
-
// Development mode with file watching
|
|
203
|
-
console.log('šļø Initial build...');
|
|
204
|
-
await clovie.build.static();
|
|
205
|
-
console.log('ā
Initial build completed\n');
|
|
206
|
-
|
|
207
|
-
// Start development server
|
|
208
|
-
clovie.server.start();
|
|
209
|
-
|
|
210
|
-
// Set up file watching
|
|
211
|
-
console.log('š Setting up file watching...');
|
|
212
|
-
|
|
213
|
-
// Debug: Check if config service is available
|
|
214
|
-
console.log(' Debug: config service available:', !!clovie.config);
|
|
215
|
-
console.log(' Debug: getWatchPaths available:', !!clovie.config?.getWatchPaths);
|
|
216
|
-
|
|
217
|
-
// Use discovered config paths from Config service
|
|
218
|
-
let watchPaths;
|
|
219
|
-
try {
|
|
220
|
-
watchPaths = clovie.config.getWatchPaths();
|
|
221
|
-
} catch (error) {
|
|
222
|
-
console.error(' Error getting watch paths:', error.message);
|
|
223
|
-
// Fallback to manual discovery for debugging
|
|
224
|
-
const discoveredConfig = clovie.config.get();
|
|
225
|
-
watchPaths = [
|
|
226
|
-
discoveredConfig?.views,
|
|
227
|
-
discoveredConfig?.partials,
|
|
228
|
-
discoveredConfig?.styles,
|
|
229
|
-
discoveredConfig?.scripts,
|
|
230
|
-
discoveredConfig?.assets
|
|
231
|
-
].filter(Boolean);
|
|
232
|
-
console.log(' Using fallback watch paths:', watchPaths);
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
console.log(` Watching ${watchPaths.length} directories:`, watchPaths);
|
|
236
|
-
|
|
237
|
-
// Set up file watchers with change handler
|
|
238
|
-
const watchers = clovie.file.watch(watchPaths, {}, {
|
|
239
|
-
onChange: async (filePath) => {
|
|
240
|
-
console.log('š Triggering rebuild...');
|
|
241
|
-
|
|
242
|
-
try {
|
|
243
|
-
const result = await clovie.build.static();
|
|
244
|
-
console.log(`ā
Rebuild completed in ${result.buildTime}ms`);
|
|
245
|
-
|
|
246
|
-
// Notify live reload
|
|
247
|
-
if (clovie.server && clovie.server.notifyReload) {
|
|
248
|
-
clovie.server.notifyReload();
|
|
249
|
-
}
|
|
250
|
-
} catch (error) {
|
|
251
|
-
console.error('ā Rebuild failed:', error.message);
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
});
|
|
216
|
+
// Execute the specific command
|
|
217
|
+
async function executeCommand(clovie, command, options) {
|
|
218
|
+
switch (command) {
|
|
219
|
+
case 'build':
|
|
220
|
+
console.log('šØ Building project...');
|
|
221
|
+
await clovie.run.build();
|
|
222
|
+
console.log('ā
Build completed successfully');
|
|
223
|
+
process.exit(0);
|
|
255
224
|
|
|
256
|
-
|
|
257
|
-
console.log('
|
|
258
|
-
|
|
225
|
+
case 'serve':
|
|
226
|
+
console.log('š Starting production server...');
|
|
227
|
+
await clovie.run.serve();
|
|
228
|
+
// Keep process alive for server
|
|
229
|
+
break;
|
|
259
230
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
process.exit(0);
|
|
267
|
-
});
|
|
231
|
+
case 'dev':
|
|
232
|
+
case 'watch':
|
|
233
|
+
console.log('š Starting development server...');
|
|
234
|
+
await clovie.run.dev();
|
|
235
|
+
// Keep process alive for dev server
|
|
236
|
+
break;
|
|
268
237
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
console.log(`š Generated ${result.filesGenerated} files`);
|
|
274
|
-
process.exit(0);
|
|
275
|
-
}
|
|
276
|
-
} catch (err) {
|
|
277
|
-
console.error(err);
|
|
278
|
-
process.exit(1);
|
|
238
|
+
default:
|
|
239
|
+
console.error(`ā Unknown command: ${command}`);
|
|
240
|
+
console.error('Available commands: build, serve, dev, watch');
|
|
241
|
+
process.exit(1);
|
|
279
242
|
}
|
|
243
|
+
|
|
244
|
+
// Setup graceful shutdown for long-running processes
|
|
245
|
+
process.on('SIGINT', () => {
|
|
246
|
+
console.log('\nš Shutting down...');
|
|
247
|
+
process.exit(0);
|
|
248
|
+
});
|
|
280
249
|
}
|
|
281
250
|
|
|
282
251
|
// Run main function
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Server } from "socket.io";
|
|
2
|
+
|
|
3
|
+
import { S as ServiceProvider, q as queueMacrotask } from "./createClovie-1_zYoNTN.js";
|
|
4
|
+
|
|
5
|
+
import "stream";
|
|
6
|
+
|
|
7
|
+
import "module";
|
|
8
|
+
|
|
9
|
+
import "path";
|
|
10
|
+
|
|
11
|
+
import "crypto";
|
|
12
|
+
|
|
13
|
+
import "fs";
|
|
14
|
+
|
|
15
|
+
import "istextorbinary";
|
|
16
|
+
|
|
17
|
+
import "chokidar";
|
|
18
|
+
|
|
19
|
+
import "readline";
|
|
20
|
+
|
|
21
|
+
import "events";
|
|
22
|
+
|
|
23
|
+
import "node:process";
|
|
24
|
+
|
|
25
|
+
import "node:os";
|
|
26
|
+
|
|
27
|
+
import "node:tty";
|
|
28
|
+
|
|
29
|
+
class LiveReload extends ServiceProvider {
|
|
30
|
+
static manifest={
|
|
31
|
+
name: "Clovie LiveReload",
|
|
32
|
+
namespace: "liveReload",
|
|
33
|
+
version: "1.0.0"
|
|
34
|
+
};
|
|
35
|
+
#io;
|
|
36
|
+
#reloading=!1;
|
|
37
|
+
getter() {
|
|
38
|
+
return {
|
|
39
|
+
io: () => this.#io
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
actions() {
|
|
43
|
+
return {
|
|
44
|
+
initializeServer: async server => {
|
|
45
|
+
const log = this.useContext("log");
|
|
46
|
+
"development" === this.config?.mode && await this.#setupSocketIO(server, log);
|
|
47
|
+
},
|
|
48
|
+
notifyReload: () => {
|
|
49
|
+
this.#reloading || (this.#reloading = !0, queueMacrotask(() => {
|
|
50
|
+
this.#reloading = !1, this.#io.emit("reload");
|
|
51
|
+
}));
|
|
52
|
+
},
|
|
53
|
+
injectLiveReloadScript: async (renderedContent, config) => {
|
|
54
|
+
const lastBodyIndex = renderedContent.lastIndexOf("</body>");
|
|
55
|
+
if (-1 !== lastBodyIndex) {
|
|
56
|
+
const scriptConfig = {
|
|
57
|
+
mode: config.mode || "development",
|
|
58
|
+
port: config.port || 3e3
|
|
59
|
+
};
|
|
60
|
+
try {
|
|
61
|
+
renderedContent = renderedContent.substring(0, lastBodyIndex) + this.#liveReloadScript(scriptConfig) + "\n" + renderedContent.substring(lastBodyIndex);
|
|
62
|
+
} catch (err) {
|
|
63
|
+
console.warn("ā ļø Could not load live reload script:", err.message);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return renderedContent;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async #setupSocketIO(server, log) {
|
|
71
|
+
try {
|
|
72
|
+
await new Promise(resolve => setTimeout(resolve, 100)), log.debug("Setting up Socket.IO..."),
|
|
73
|
+
this.#io = new Server(server, {
|
|
74
|
+
cors: {
|
|
75
|
+
origin: "*",
|
|
76
|
+
methods: [ "GET", "POST" ]
|
|
77
|
+
},
|
|
78
|
+
transports: [ "polling", "websocket" ],
|
|
79
|
+
allowEIO3: !0
|
|
80
|
+
}), this.#io.on("connection", socket => {
|
|
81
|
+
log.debug(`Client connected: ${socket.id}`), socket.on("disconnect", reason => {
|
|
82
|
+
log.debug(`Client disconnected: ${socket.id} - ${reason}`);
|
|
83
|
+
}), socket.on("error", error => {
|
|
84
|
+
log.error("Socket error:", error);
|
|
85
|
+
});
|
|
86
|
+
}), log.info("Socket.IO server ready");
|
|
87
|
+
} catch (error) {
|
|
88
|
+
log.error("Error setting up Socket.IO:", error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
#liveReloadScript=config => `\x3c!-- Live Reload Script (Development Mode Only) --\x3e\n<script src="https://cdn.socket.io/4.7.4/socket.io.min.js"><\/script>\n<script>\n (function() {\n const config = ${JSON.stringify(config)};\n \n console.log('Initializing live reload with config:', config);\n \n // Configure Socket.IO client with proper options\n const socket = io({\n transports: ['polling', 'websocket'],\n timeout: 20000,\n forceNew: true\n });\n \n socket.on('reload', () => {\n console.log('Live reload triggered');\n window.location.reload();\n });\n \n socket.on('connect', () => {\n console.log('Connected to live reload server');\n });\n \n socket.on('disconnect', (reason) => {\n console.log('Disconnected from live reload server:', reason);\n });\n \n socket.on('connect_error', (error) => {\n console.error('Connection error:', error);\n console.log('Retrying connection in 3 seconds...');\n setTimeout(() => {\n socket.connect();\n }, 3000);\n });\n \n socket.on('error', (error) => {\n console.error('Socket error:', error);\n });\n \n // Add connection timeout\n setTimeout(() => {\n if (!socket.connected) {\n console.warn('Live reload connection timeout - server may not be running');\n }\n }, 5000);\n })();\n<\/script>`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { LiveReload };
|
|
95
|
+
//# sourceMappingURL=LiveReload-CGbacq3U.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LiveReload-CGbacq3U.js","sources":["../lib/LiveReload.js"],"sourcesContent":["import { Server as SocketIOServer } from 'socket.io';\nimport { ServiceProvider } from '@brickworks/engine';\nimport { queueMacrotask } from './utils/tasks.js';\n\nexport class LiveReload extends ServiceProvider {\n static manifest = {\n name: 'Clovie LiveReload',\n namespace: 'liveReload',\n version: '1.0.0',\n };\n\n #io;\n #reloading = false;\n\n getter () {\n return {\n io: () => this.#io,\n }\n }\n\n actions() {\n return {\n initializeServer: async (server) => {\n const log = this.useContext('log');\n if (this.config?.mode === 'development') {\n await this.#setupSocketIO(server, log);\n }\n },\n notifyReload: () => {\n if (this.#reloading) return;\n this.#reloading = true;\n \n queueMacrotask(() => {\n this.#reloading = false;\n this.#io.emit('reload')\n });\n },\n injectLiveReloadScript: async (renderedContent, config) => {\n const lastBodyIndex = renderedContent.lastIndexOf('</body>');\n if (lastBodyIndex !== -1) {\n const scriptConfig = { \n mode: config.mode || 'development', \n port: config.port || 3000 \n };\n \n try {\n // Import live reload script dynamically \n renderedContent = renderedContent.substring(0, lastBodyIndex) + \n this.#liveReloadScript(scriptConfig) + '\\n' + \n renderedContent.substring(lastBodyIndex);\n } catch (err) {\n console.warn('ā ļø Could not load live reload script:', err.message);\n }\n }\n return renderedContent;\n }\n }\n }\n\n async #setupSocketIO(server, log) {\n try {\n // Wait a bit for server to be fully initialized\n await new Promise(resolve => setTimeout(resolve, 100));\n\n log.debug('Setting up Socket.IO...');\n \n // Configure Socket.IO with proper CORS and options\n this.#io = new SocketIOServer(server, {\n cors: {\n origin: \"*\",\n methods: [\"GET\", \"POST\"]\n },\n transports: ['polling', 'websocket'],\n allowEIO3: true\n });\n\n this.#io.on('connection', (socket) => {\n log.debug(`Client connected: ${socket.id}`);\n \n socket.on('disconnect', (reason) => {\n log.debug(`Client disconnected: ${socket.id} - ${reason}`);\n });\n \n socket.on('error', (error) => {\n log.error('Socket error:', error);\n });\n });\n\n log.info('Socket.IO server ready');\n } catch (error) {\n log.error('Error setting up Socket.IO:', error);\n }\n }\n\n #liveReloadScript = (config) => `<!-- Live Reload Script (Development Mode Only) -->\n<script src=\"https://cdn.socket.io/4.7.4/socket.io.min.js\"></script>\n<script>\n (function() {\n const config = ${JSON.stringify(config)};\n \n console.log('Initializing live reload with config:', config);\n \n // Configure Socket.IO client with proper options\n const socket = io({\n transports: ['polling', 'websocket'],\n timeout: 20000,\n forceNew: true\n });\n \n socket.on('reload', () => {\n console.log('Live reload triggered');\n window.location.reload();\n });\n \n socket.on('connect', () => {\n console.log('Connected to live reload server');\n });\n \n socket.on('disconnect', (reason) => {\n console.log('Disconnected from live reload server:', reason);\n });\n \n socket.on('connect_error', (error) => {\n console.error('Connection error:', error);\n console.log('Retrying connection in 3 seconds...');\n setTimeout(() => {\n socket.connect();\n }, 3000);\n });\n \n socket.on('error', (error) => {\n console.error('Socket error:', error);\n });\n \n // Add connection timeout\n setTimeout(() => {\n if (!socket.connected) {\n console.warn('Live reload connection timeout - server may not be running');\n }\n }, 5000);\n })();\n</script>`;\n}"],"names":["LiveReload","ServiceProvider","static","name","namespace","version","io","reloading","getter","this","actions","initializeServer","async","server","log","useContext","config","mode","setupSocketIO","notifyReload","queueMacrotask","emit","injectLiveReloadScript","renderedContent","lastBodyIndex","lastIndexOf","scriptConfig","port","substring","liveReloadScript","err","console","warn","message","Promise","resolve","setTimeout","debug","SocketIOServer","cors","origin","methods","transports","allowEIO3","on","socket","id","reason","error","info","JSON","stringify"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAIO,MAAMA,mBAAmBC;IAC9BC,gBAAkB;QAChBC,MAAM;QACNC,WAAW;QACXC,SAAS;;IAGXC;IACAC,YAAa;IAEb,MAAAC;QACE,OAAO;YACLF,IAAI,MAAMG,MAAKH;;AAEnB;IAEA,OAAAI;QACE,OAAO;YACLC,kBAAkBC,MAAOC;gBACvB,MAAMC,MAAML,KAAKM,WAAW;gBACF,kBAAtBN,KAAKO,QAAQC,cACTR,MAAKS,cAAeL,QAAQC;;YAGtCK,cAAc;gBACRV,MAAKF,cACTE,MAAKF,aAAa,GAElBa,eAAe;oBACbX,MAAKF,aAAa,GAClBE,MAAKH,GAAIe,KAAK;;;YAGlBC,wBAAwBV,OAAOW,iBAAiBP;gBAC9C,MAAMQ,gBAAgBD,gBAAgBE,YAAY;gBAClD,KAAsB,MAAlBD,eAAsB;oBACxB,MAAME,eAAe;wBACnBT,MAAMD,OAAOC,QAAQ;wBACrBU,MAAMX,OAAOW,QAAQ;;oBAGvB;wBAEEJ,kBAAkBA,gBAAgBK,UAAU,GAAGJ,iBAC/Bf,MAAKoB,iBAAkBH,gBAAgB,OACvCH,gBAAgBK,UAAUJ;AAC5C,sBAAE,OAAOM;wBACPC,QAAQC,KAAK,0CAA0CF,IAAIG;AAC7D;AACF;gBACA,OAAOV;;;AAGb;IAEA,oBAAML,CAAeL,QAAQC;QAC3B;kBAEQ,IAAIoB,QAAQC,WAAWC,WAAWD,SAAS,OAEjDrB,IAAIuB,MAAM;YAGV5B,MAAKH,KAAM,IAAIgC,OAAezB,QAAQ;gBACpC0B,MAAM;oBACJC,QAAQ;oBACRC,SAAS,EAAC,OAAO;;gBAEnBC,YAAY,EAAC,WAAW;gBACxBC,YAAW;gBAGblC,MAAKH,GAAIsC,GAAG,cAAeC;gBACzB/B,IAAIuB,MAAM,qBAAqBQ,OAAOC,OAEtCD,OAAOD,GAAG,cAAeG;oBACvBjC,IAAIuB,MAAM,wBAAwBQ,OAAOC,QAAQC;oBAGnDF,OAAOD,GAAG,SAAUI;oBAClBlC,IAAIkC,MAAM,iBAAiBA;;gBAI/BlC,IAAImC,KAAK;AACX,UAAE,OAAOD;YACPlC,IAAIkC,MAAM,+BAA+BA;AAC3C;AACF;IAEAnB,kBAAqBb,UAAW,mLAIbkC,KAAKC,UAAUnC;;;"}
|