claude-cortex 1.5.0 → 1.5.2
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/dashboard/package.json +2 -1
- package/dashboard/scripts/ensure-api.mjs +76 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/service/install.d.ts +13 -0
- package/dist/service/install.d.ts.map +1 -0
- package/dist/service/install.js +168 -0
- package/dist/service/install.js.map +1 -0
- package/dist/service/templates.d.ts +13 -0
- package/dist/service/templates.d.ts.map +1 -0
- package/dist/service/templates.js +58 -0
- package/dist/service/templates.js.map +1 -0
- package/package.json +1 -1
package/dashboard/package.json
CHANGED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Ensures the API server is running before starting the dashboard.
|
|
4
|
+
* Automatically spawns the API if it's not reachable.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { spawn } from 'child_process';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { dirname, join } from 'path';
|
|
10
|
+
|
|
11
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const rootDir = join(__dirname, '..', '..');
|
|
13
|
+
|
|
14
|
+
const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3001';
|
|
15
|
+
const HEALTH_ENDPOINT = `${API_URL}/api/health`;
|
|
16
|
+
const MAX_WAIT_MS = 10000;
|
|
17
|
+
const POLL_INTERVAL_MS = 500;
|
|
18
|
+
|
|
19
|
+
async function checkApiHealth() {
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch(HEALTH_ENDPOINT, {
|
|
22
|
+
signal: AbortSignal.timeout(2000)
|
|
23
|
+
});
|
|
24
|
+
return response.ok;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function waitForApi(timeoutMs) {
|
|
31
|
+
const start = Date.now();
|
|
32
|
+
while (Date.now() - start < timeoutMs) {
|
|
33
|
+
if (await checkApiHealth()) {
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
await new Promise(r => setTimeout(r, POLL_INTERVAL_MS));
|
|
37
|
+
}
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function main() {
|
|
42
|
+
console.log('[Dashboard] Checking if API server is running...');
|
|
43
|
+
|
|
44
|
+
if (await checkApiHealth()) {
|
|
45
|
+
console.log('[Dashboard] API server is already running ✓');
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
console.log('[Dashboard] API server not detected, starting it...');
|
|
50
|
+
|
|
51
|
+
// Spawn API server in background (fully detached)
|
|
52
|
+
// Using 'ignore' for all stdio to prevent SIGPIPE when parent exits
|
|
53
|
+
const apiProcess = spawn('npm', ['run', 'dev:api'], {
|
|
54
|
+
cwd: rootDir,
|
|
55
|
+
detached: true,
|
|
56
|
+
stdio: 'ignore',
|
|
57
|
+
shell: true,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// Fully detach - allow parent to exit without killing child
|
|
61
|
+
apiProcess.unref();
|
|
62
|
+
|
|
63
|
+
// Wait for API to be ready
|
|
64
|
+
console.log('[Dashboard] Waiting for API server to be ready...');
|
|
65
|
+
const ready = await waitForApi(MAX_WAIT_MS);
|
|
66
|
+
|
|
67
|
+
if (ready) {
|
|
68
|
+
console.log('[Dashboard] API server is ready ✓');
|
|
69
|
+
process.exit(0);
|
|
70
|
+
} else {
|
|
71
|
+
console.error('[Dashboard] API server failed to start within timeout');
|
|
72
|
+
process.exit(1);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
main();
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* npx claude-cortex --mode both # Start both servers
|
|
13
13
|
* npx claude-cortex --dashboard # Start API + Dashboard (admin panel)
|
|
14
14
|
* npx claude-cortex --db /path/to.db # Custom database path
|
|
15
|
+
* npx claude-cortex service install # Auto-start dashboard on login
|
|
16
|
+
* npx claude-cortex service uninstall # Remove auto-start
|
|
17
|
+
* npx claude-cortex service status # Check service status
|
|
15
18
|
*/
|
|
16
19
|
export {};
|
|
17
20
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;;;GAgBG"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* npx claude-cortex --mode both # Start both servers
|
|
13
13
|
* npx claude-cortex --dashboard # Start API + Dashboard (admin panel)
|
|
14
14
|
* npx claude-cortex --db /path/to.db # Custom database path
|
|
15
|
+
* npx claude-cortex service install # Auto-start dashboard on login
|
|
16
|
+
* npx claude-cortex service uninstall # Remove auto-start
|
|
17
|
+
* npx claude-cortex service status # Check service status
|
|
15
18
|
*/
|
|
16
19
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
17
20
|
import { spawn } from 'child_process';
|
|
@@ -19,6 +22,7 @@ import { fileURLToPath } from 'url';
|
|
|
19
22
|
import path from 'path';
|
|
20
23
|
import { createServer } from './server.js';
|
|
21
24
|
import { startVisualizationServer } from './api/visualization-server.js';
|
|
25
|
+
import { handleServiceCommand } from './service/install.js';
|
|
22
26
|
// Get the directory of this file for relative paths
|
|
23
27
|
const __filename = fileURLToPath(import.meta.url);
|
|
24
28
|
const __dirname = path.dirname(__filename);
|
|
@@ -116,6 +120,11 @@ function startDashboard() {
|
|
|
116
120
|
* Main entry point
|
|
117
121
|
*/
|
|
118
122
|
async function main() {
|
|
123
|
+
// Handle "service" subcommand before normal mode parsing
|
|
124
|
+
if (process.argv[2] === 'service') {
|
|
125
|
+
await handleServiceCommand(process.argv[3] || '');
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
119
128
|
const { dbPath, mode } = parseArgs();
|
|
120
129
|
let dashboardProcess = null;
|
|
121
130
|
if (mode === 'api') {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform service installer for Claude Cortex dashboard auto-start.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - macOS: LaunchAgent plist
|
|
6
|
+
* - Linux: systemd user service
|
|
7
|
+
* - Windows: VBS script in Startup folder
|
|
8
|
+
*/
|
|
9
|
+
export declare function installService(): Promise<void>;
|
|
10
|
+
export declare function uninstallService(): Promise<void>;
|
|
11
|
+
export declare function serviceStatus(): Promise<void>;
|
|
12
|
+
export declare function handleServiceCommand(subcommand: string): Promise<void>;
|
|
13
|
+
//# sourceMappingURL=install.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/service/install.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA+CH,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAmDpD;AAED,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CA2BtD;AAED,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAgCnD;AAED,wBAAsB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe5E"}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cross-platform service installer for Claude Cortex dashboard auto-start.
|
|
3
|
+
*
|
|
4
|
+
* Supports:
|
|
5
|
+
* - macOS: LaunchAgent plist
|
|
6
|
+
* - Linux: systemd user service
|
|
7
|
+
* - Windows: VBS script in Startup folder
|
|
8
|
+
*/
|
|
9
|
+
import fs from 'fs';
|
|
10
|
+
import path from 'path';
|
|
11
|
+
import os from 'os';
|
|
12
|
+
import { execSync } from 'child_process';
|
|
13
|
+
import { fileURLToPath } from 'url';
|
|
14
|
+
import { launchdPlist, systemdUnit, windowsVbs } from './templates.js';
|
|
15
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
16
|
+
const __dirname = path.dirname(__filename);
|
|
17
|
+
function detectPlatform() {
|
|
18
|
+
switch (process.platform) {
|
|
19
|
+
case 'darwin': return 'macos';
|
|
20
|
+
case 'win32': return 'windows';
|
|
21
|
+
default: return 'linux';
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
function getServiceConfig() {
|
|
25
|
+
const logsDir = path.join(os.homedir(), '.claude-cortex', 'logs');
|
|
26
|
+
fs.mkdirSync(logsDir, { recursive: true });
|
|
27
|
+
return {
|
|
28
|
+
nodePath: process.execPath,
|
|
29
|
+
nodeBinDir: path.dirname(process.execPath),
|
|
30
|
+
entryPoint: path.resolve(__dirname, '..', 'index.js'),
|
|
31
|
+
logsDir,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function getServicePath(platform) {
|
|
35
|
+
switch (platform) {
|
|
36
|
+
case 'macos':
|
|
37
|
+
return path.join(os.homedir(), 'Library', 'LaunchAgents', 'com.claude-cortex.dashboard.plist');
|
|
38
|
+
case 'linux':
|
|
39
|
+
return path.join(os.homedir(), '.config', 'systemd', 'user', 'claude-cortex-dashboard.service');
|
|
40
|
+
case 'windows': {
|
|
41
|
+
const appData = process.env.APPDATA || path.join(os.homedir(), 'AppData', 'Roaming');
|
|
42
|
+
return path.join(appData, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Startup', 'claude-cortex-dashboard.vbs');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export async function installService() {
|
|
47
|
+
const platform = detectPlatform();
|
|
48
|
+
const config = getServiceConfig();
|
|
49
|
+
const servicePath = getServicePath(platform);
|
|
50
|
+
// Ensure parent directory exists
|
|
51
|
+
fs.mkdirSync(path.dirname(servicePath), { recursive: true });
|
|
52
|
+
// Generate and write service file
|
|
53
|
+
let content;
|
|
54
|
+
switch (platform) {
|
|
55
|
+
case 'macos':
|
|
56
|
+
content = launchdPlist(config);
|
|
57
|
+
break;
|
|
58
|
+
case 'linux':
|
|
59
|
+
content = systemdUnit(config);
|
|
60
|
+
break;
|
|
61
|
+
case 'windows':
|
|
62
|
+
content = windowsVbs(config);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
fs.writeFileSync(servicePath, content, 'utf-8');
|
|
66
|
+
console.log(`Service file written to: ${servicePath}`);
|
|
67
|
+
// Enable and start the service
|
|
68
|
+
try {
|
|
69
|
+
switch (platform) {
|
|
70
|
+
case 'macos':
|
|
71
|
+
execSync(`launchctl load -w "${servicePath}"`, { stdio: 'inherit' });
|
|
72
|
+
console.log('Service loaded via launchctl.');
|
|
73
|
+
break;
|
|
74
|
+
case 'linux':
|
|
75
|
+
execSync('systemctl --user daemon-reload', { stdio: 'inherit' });
|
|
76
|
+
execSync('systemctl --user enable --now claude-cortex-dashboard.service', { stdio: 'inherit' });
|
|
77
|
+
console.log('Service enabled via systemd.');
|
|
78
|
+
break;
|
|
79
|
+
case 'windows':
|
|
80
|
+
console.log('Service installed. It will start on next login.');
|
|
81
|
+
console.log('To start now, run the VBS script or reboot.');
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
catch (err) {
|
|
86
|
+
console.error(`Failed to enable service: ${err.message}`);
|
|
87
|
+
console.log(`The service file was written to ${servicePath} — you can enable it manually.`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
console.log('\nClaude Cortex dashboard will now auto-start on login.');
|
|
91
|
+
console.log(` API: http://localhost:3001`);
|
|
92
|
+
console.log(` Dashboard: http://localhost:3030`);
|
|
93
|
+
}
|
|
94
|
+
export async function uninstallService() {
|
|
95
|
+
const platform = detectPlatform();
|
|
96
|
+
const servicePath = getServicePath(platform);
|
|
97
|
+
if (!fs.existsSync(servicePath)) {
|
|
98
|
+
console.log('No service installed.');
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
switch (platform) {
|
|
103
|
+
case 'macos':
|
|
104
|
+
execSync(`launchctl unload -w "${servicePath}"`, { stdio: 'inherit' });
|
|
105
|
+
break;
|
|
106
|
+
case 'linux':
|
|
107
|
+
execSync('systemctl --user disable --now claude-cortex-dashboard.service', { stdio: 'inherit' });
|
|
108
|
+
break;
|
|
109
|
+
case 'windows':
|
|
110
|
+
// Just delete the file — no daemon to stop
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch {
|
|
115
|
+
// Service may not be loaded, continue to delete file
|
|
116
|
+
}
|
|
117
|
+
fs.unlinkSync(servicePath);
|
|
118
|
+
console.log(`Service removed: ${servicePath}`);
|
|
119
|
+
}
|
|
120
|
+
export async function serviceStatus() {
|
|
121
|
+
const platform = detectPlatform();
|
|
122
|
+
const servicePath = getServicePath(platform);
|
|
123
|
+
const installed = fs.existsSync(servicePath);
|
|
124
|
+
console.log(`Platform: ${platform}`);
|
|
125
|
+
console.log(`Installed: ${installed ? 'yes' : 'no'}`);
|
|
126
|
+
console.log(`Path: ${servicePath}`);
|
|
127
|
+
if (!installed)
|
|
128
|
+
return;
|
|
129
|
+
// Check if running
|
|
130
|
+
try {
|
|
131
|
+
switch (platform) {
|
|
132
|
+
case 'macos': {
|
|
133
|
+
const out = execSync('launchctl list com.claude-cortex.dashboard 2>&1', { encoding: 'utf-8' });
|
|
134
|
+
const pidMatch = out.match(/"PID"\s*=\s*(\d+)/);
|
|
135
|
+
console.log(`Running: ${pidMatch ? `yes (PID ${pidMatch[1]})` : 'no'}`);
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
case 'linux': {
|
|
139
|
+
const out = execSync('systemctl --user is-active claude-cortex-dashboard.service 2>&1', { encoding: 'utf-8' }).trim();
|
|
140
|
+
console.log(`Running: ${out === 'active' ? 'yes' : 'no'}`);
|
|
141
|
+
break;
|
|
142
|
+
}
|
|
143
|
+
case 'windows':
|
|
144
|
+
console.log('Running: (check Task Manager for node.exe)');
|
|
145
|
+
break;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch {
|
|
149
|
+
console.log('Running: no');
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
export async function handleServiceCommand(subcommand) {
|
|
153
|
+
switch (subcommand) {
|
|
154
|
+
case 'install':
|
|
155
|
+
await installService();
|
|
156
|
+
break;
|
|
157
|
+
case 'uninstall':
|
|
158
|
+
await uninstallService();
|
|
159
|
+
break;
|
|
160
|
+
case 'status':
|
|
161
|
+
await serviceStatus();
|
|
162
|
+
break;
|
|
163
|
+
default:
|
|
164
|
+
console.log('Usage: claude-cortex service <install|uninstall|status>');
|
|
165
|
+
process.exit(1);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
//# sourceMappingURL=install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/service/install.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-specific service file templates for auto-starting Claude Cortex dashboard.
|
|
3
|
+
*/
|
|
4
|
+
export interface ServiceConfig {
|
|
5
|
+
nodePath: string;
|
|
6
|
+
nodeBinDir: string;
|
|
7
|
+
entryPoint: string;
|
|
8
|
+
logsDir: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function launchdPlist(config: ServiceConfig): string;
|
|
11
|
+
export declare function systemdUnit(config: ServiceConfig): string;
|
|
12
|
+
export declare function windowsVbs(config: ServiceConfig): string;
|
|
13
|
+
//# sourceMappingURL=templates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/service/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CA6B1D;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAgBzD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAMxD"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Platform-specific service file templates for auto-starting Claude Cortex dashboard.
|
|
3
|
+
*/
|
|
4
|
+
export function launchdPlist(config) {
|
|
5
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
6
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
7
|
+
<plist version="1.0">
|
|
8
|
+
<dict>
|
|
9
|
+
<key>Label</key>
|
|
10
|
+
<string>com.claude-cortex.dashboard</string>
|
|
11
|
+
<key>ProgramArguments</key>
|
|
12
|
+
<array>
|
|
13
|
+
<string>${config.nodePath}</string>
|
|
14
|
+
<string>${config.entryPoint}</string>
|
|
15
|
+
<string>--mode</string>
|
|
16
|
+
<string>dashboard</string>
|
|
17
|
+
</array>
|
|
18
|
+
<key>RunAtLoad</key>
|
|
19
|
+
<true/>
|
|
20
|
+
<key>KeepAlive</key>
|
|
21
|
+
<true/>
|
|
22
|
+
<key>StandardOutPath</key>
|
|
23
|
+
<string>${config.logsDir}/dashboard-stdout.log</string>
|
|
24
|
+
<key>StandardErrorPath</key>
|
|
25
|
+
<string>${config.logsDir}/dashboard-stderr.log</string>
|
|
26
|
+
<key>EnvironmentVariables</key>
|
|
27
|
+
<dict>
|
|
28
|
+
<key>PATH</key>
|
|
29
|
+
<string>${config.nodeBinDir}:/usr/local/bin:/usr/bin:/bin</string>
|
|
30
|
+
</dict>
|
|
31
|
+
</dict>
|
|
32
|
+
</plist>`;
|
|
33
|
+
}
|
|
34
|
+
export function systemdUnit(config) {
|
|
35
|
+
return `[Unit]
|
|
36
|
+
Description=Claude Cortex Dashboard
|
|
37
|
+
After=network.target
|
|
38
|
+
|
|
39
|
+
[Service]
|
|
40
|
+
Type=simple
|
|
41
|
+
ExecStart=${config.nodePath} ${config.entryPoint} --mode dashboard
|
|
42
|
+
Restart=on-failure
|
|
43
|
+
RestartSec=5
|
|
44
|
+
StandardOutput=append:${config.logsDir}/dashboard-stdout.log
|
|
45
|
+
StandardError=append:${config.logsDir}/dashboard-stderr.log
|
|
46
|
+
Environment=PATH=${config.nodeBinDir}:/usr/local/bin:/usr/bin:/bin
|
|
47
|
+
|
|
48
|
+
[Install]
|
|
49
|
+
WantedBy=default.target`;
|
|
50
|
+
}
|
|
51
|
+
export function windowsVbs(config) {
|
|
52
|
+
// VBS script runs node hidden (no console window)
|
|
53
|
+
const nodePath = config.nodePath.replace(/\//g, '\\');
|
|
54
|
+
const entryPoint = config.entryPoint.replace(/\//g, '\\');
|
|
55
|
+
return `Set WshShell = CreateObject("WScript.Shell")
|
|
56
|
+
WshShell.Run """${nodePath}"" ""${entryPoint}"" --mode dashboard", 0, False`;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=templates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/service/templates.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,MAAM,UAAU,YAAY,CAAC,MAAqB;IAChD,OAAO;;;;;;;;cAQK,MAAM,CAAC,QAAQ;cACf,MAAM,CAAC,UAAU;;;;;;;;;YASnB,MAAM,CAAC,OAAO;;YAEd,MAAM,CAAC,OAAO;;;;cAIZ,MAAM,CAAC,UAAU;;;SAGtB,CAAC;AACV,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAqB;IAC/C,OAAO;;;;;;YAMG,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,UAAU;;;wBAGxB,MAAM,CAAC,OAAO;uBACf,MAAM,CAAC,OAAO;mBAClB,MAAM,CAAC,UAAU;;;wBAGZ,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAAqB;IAC9C,kDAAkD;IAClD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC1D,OAAO;kBACS,QAAQ,QAAQ,UAAU,gCAAgC,CAAC;AAC7E,CAAC"}
|