devflow-kit 0.3.3 โ 0.5.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/CHANGELOG.md +131 -0
- package/README.md +84 -15
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +202 -190
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/uninstall.d.ts.map +1 -1
- package/dist/commands/uninstall.js +77 -63
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/utils/git.d.ts +11 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +36 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/paths.d.ts +32 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +86 -0
- package/dist/utils/paths.js.map +1 -0
- package/package.json +1 -1
- package/src/claude/agents/devflow/debug.md +475 -0
- package/src/claude/agents/devflow/project-state.md +419 -0
- package/src/claude/commands/devflow/debug.md +29 -201
- package/src/claude/commands/devflow/devlog.md +211 -172
- package/src/claude/commands/devflow/implement.md +507 -0
- package/src/claude/skills/devflow/code-smell/SKILL.md +428 -0
- package/src/claude/skills/devflow/debug/SKILL.md +119 -0
- package/src/claude/skills/devflow/error-handling/SKILL.md +597 -0
- package/src/claude/skills/devflow/input-validation/SKILL.md +514 -0
- package/src/claude/skills/devflow/pattern-check/SKILL.md +238 -0
- package/src/claude/skills/devflow/research/SKILL.md +135 -0
- package/src/claude/skills/devflow/test-design/SKILL.md +384 -0
|
@@ -1,82 +1,96 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { promises as fs } from 'fs';
|
|
3
3
|
import * as path from 'path';
|
|
4
|
-
import {
|
|
4
|
+
import { getInstallationPaths, getClaudeDirectory } from '../utils/paths.js';
|
|
5
|
+
import { getGitRoot } from '../utils/git.js';
|
|
5
6
|
/**
|
|
6
|
-
*
|
|
7
|
-
* Priority: process.env.HOME > os.homedir()
|
|
7
|
+
* Check if DevFlow is installed at the given paths
|
|
8
8
|
*/
|
|
9
|
-
function
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
return home;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* Get Claude Code directory with environment variable override support
|
|
18
|
-
* Priority: CLAUDE_CODE_DIR env var > ~/.claude
|
|
19
|
-
*/
|
|
20
|
-
function getClaudeDirectory() {
|
|
21
|
-
if (process.env.CLAUDE_CODE_DIR) {
|
|
22
|
-
return process.env.CLAUDE_CODE_DIR;
|
|
9
|
+
async function isDevFlowInstalled(claudeDir) {
|
|
10
|
+
try {
|
|
11
|
+
await fs.access(path.join(claudeDir, 'commands', 'devflow'));
|
|
12
|
+
return true;
|
|
23
13
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Get DevFlow directory with environment variable override support
|
|
28
|
-
* Priority: DEVFLOW_DIR env var > ~/.devflow
|
|
29
|
-
*/
|
|
30
|
-
function getDevFlowDirectory() {
|
|
31
|
-
if (process.env.DEVFLOW_DIR) {
|
|
32
|
-
return process.env.DEVFLOW_DIR;
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
33
16
|
}
|
|
34
|
-
return path.join(getHomeDirectory(), '.devflow');
|
|
35
17
|
}
|
|
36
18
|
export const uninstallCommand = new Command('uninstall')
|
|
37
19
|
.description('Uninstall DevFlow from Claude Code')
|
|
38
20
|
.option('--keep-docs', 'Keep .docs/ directory and documentation')
|
|
21
|
+
.option('--scope <type>', 'Uninstall from specific scope only (default: auto-detect all)', /^(user|local)$/i)
|
|
39
22
|
.action(async (options) => {
|
|
40
23
|
console.log('๐งน Uninstalling DevFlow...\n');
|
|
41
|
-
|
|
42
|
-
let
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
devflowScriptsDir = getDevFlowDirectory();
|
|
24
|
+
// Determine which scopes to uninstall
|
|
25
|
+
let scopesToUninstall = [];
|
|
26
|
+
if (options.scope) {
|
|
27
|
+
scopesToUninstall = [options.scope.toLowerCase()];
|
|
46
28
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
29
|
+
else {
|
|
30
|
+
// Auto-detect installed scopes
|
|
31
|
+
const userClaudeDir = getClaudeDirectory();
|
|
32
|
+
const gitRoot = await getGitRoot();
|
|
33
|
+
if (await isDevFlowInstalled(userClaudeDir)) {
|
|
34
|
+
scopesToUninstall.push('user');
|
|
35
|
+
}
|
|
36
|
+
if (gitRoot) {
|
|
37
|
+
const localClaudeDir = path.join(gitRoot, '.claude');
|
|
38
|
+
if (await isDevFlowInstalled(localClaudeDir)) {
|
|
39
|
+
scopesToUninstall.push('local');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (scopesToUninstall.length === 0) {
|
|
43
|
+
console.log('โ No DevFlow installation found');
|
|
44
|
+
console.log(' Checked user scope (~/.claude/) and local scope (git-root/.claude/)\n');
|
|
45
|
+
process.exit(1);
|
|
46
|
+
}
|
|
47
|
+
if (scopesToUninstall.length > 1) {
|
|
48
|
+
console.log('๐ฆ Found DevFlow in multiple scopes:');
|
|
49
|
+
console.log(' - User scope (~/.claude/)');
|
|
50
|
+
console.log(' - Local scope (git-root/.claude/)');
|
|
51
|
+
console.log('\n Uninstalling from both...\n');
|
|
52
|
+
}
|
|
50
53
|
}
|
|
51
54
|
let hasErrors = false;
|
|
52
|
-
//
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
55
|
+
// Uninstall from each scope
|
|
56
|
+
for (const scope of scopesToUninstall) {
|
|
57
|
+
// Get installation paths for this scope
|
|
58
|
+
let claudeDir;
|
|
59
|
+
let devflowScriptsDir;
|
|
60
|
+
try {
|
|
61
|
+
const paths = await getInstallationPaths(scope);
|
|
62
|
+
claudeDir = paths.claudeDir;
|
|
63
|
+
devflowScriptsDir = paths.devflowDir;
|
|
64
|
+
if (scope === 'user') {
|
|
65
|
+
console.log('๐ Uninstalling user scope (~/.claude/)');
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
console.log('๐ Uninstalling local scope (git-root/.claude/)');
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
console.log(`โ ๏ธ Cannot uninstall ${scope} scope: ${error instanceof Error ? error.message : error}\n`);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
// DevFlow namespace directories to remove
|
|
76
|
+
const devflowDirectories = [
|
|
77
|
+
{ path: path.join(claudeDir, 'commands', 'devflow'), name: 'commands' },
|
|
78
|
+
{ path: path.join(claudeDir, 'agents', 'devflow'), name: 'agents' },
|
|
79
|
+
{ path: path.join(claudeDir, 'skills', 'devflow'), name: 'skills' },
|
|
80
|
+
{ path: devflowScriptsDir, name: 'scripts' }
|
|
81
|
+
];
|
|
82
|
+
// Remove all DevFlow directories
|
|
83
|
+
for (const dir of devflowDirectories) {
|
|
84
|
+
try {
|
|
85
|
+
await fs.rm(dir.path, { recursive: true, force: true });
|
|
86
|
+
console.log(` โ
Removed DevFlow ${dir.name}`);
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
console.error(` โ ๏ธ Could not remove ${dir.name}:`, error);
|
|
90
|
+
hasErrors = true;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
console.log();
|
|
80
94
|
}
|
|
81
95
|
// Handle .docs directory
|
|
82
96
|
if (!options.keepDocs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/cli/commands/uninstall.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"uninstall.js","sourceRoot":"","sources":["../../src/cli/commands/uninstall.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get git repository root directory (async, non-blocking)
|
|
3
|
+
* Returns null if not in a git repository
|
|
4
|
+
*
|
|
5
|
+
* Security: Validates output to prevent command injection
|
|
6
|
+
* - Rejects paths with injection characters (newlines, semicolons, shell operators)
|
|
7
|
+
* - Ensures path is absolute
|
|
8
|
+
* - Resolves path canonically
|
|
9
|
+
*/
|
|
10
|
+
export declare function getGitRoot(): Promise<string | null>;
|
|
11
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/cli/utils/git.ts"],"names":[],"mappings":"AAMA;;;;;;;;GAQG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAwBzD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { promisify } from 'util';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
const execAsync = promisify(exec);
|
|
5
|
+
/**
|
|
6
|
+
* Get git repository root directory (async, non-blocking)
|
|
7
|
+
* Returns null if not in a git repository
|
|
8
|
+
*
|
|
9
|
+
* Security: Validates output to prevent command injection
|
|
10
|
+
* - Rejects paths with injection characters (newlines, semicolons, shell operators)
|
|
11
|
+
* - Ensures path is absolute
|
|
12
|
+
* - Resolves path canonically
|
|
13
|
+
*/
|
|
14
|
+
export async function getGitRoot() {
|
|
15
|
+
try {
|
|
16
|
+
const { stdout } = await execAsync('git rev-parse --show-toplevel', {
|
|
17
|
+
cwd: process.cwd(),
|
|
18
|
+
encoding: 'utf-8'
|
|
19
|
+
});
|
|
20
|
+
const gitRootRaw = stdout.trim();
|
|
21
|
+
// Validate git root path (security: prevent injection)
|
|
22
|
+
if (!gitRootRaw || gitRootRaw.includes('\n') || gitRootRaw.includes(';') || gitRootRaw.includes('&&')) {
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
25
|
+
// Validate it's an absolute path
|
|
26
|
+
const gitRoot = path.resolve(gitRootRaw);
|
|
27
|
+
if (!path.isAbsolute(gitRoot)) {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
return gitRoot;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/cli/utils/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,+BAA+B,EAAE;YAClE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE;YAClB,QAAQ,EAAE,OAAO;SAClB,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC;QAEjC,uDAAuD;QACvD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACtG,OAAO,IAAI,CAAC;QACd,CAAC;QAED,iCAAiC;QACjC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9B,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,OAAO,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get home directory with proper fallback and validation
|
|
3
|
+
* Priority: process.env.HOME > os.homedir()
|
|
4
|
+
*
|
|
5
|
+
* @throws {Error} If unable to determine home directory
|
|
6
|
+
*/
|
|
7
|
+
export declare function getHomeDirectory(): string;
|
|
8
|
+
/**
|
|
9
|
+
* Get Claude Code directory with environment variable override support
|
|
10
|
+
* Priority: CLAUDE_CODE_DIR env var > ~/.claude
|
|
11
|
+
*
|
|
12
|
+
* @throws {Error} If CLAUDE_CODE_DIR is invalid (not absolute, outside home)
|
|
13
|
+
*/
|
|
14
|
+
export declare function getClaudeDirectory(): string;
|
|
15
|
+
/**
|
|
16
|
+
* Get DevFlow directory with environment variable override support
|
|
17
|
+
* Priority: DEVFLOW_DIR env var > ~/.devflow
|
|
18
|
+
*
|
|
19
|
+
* @throws {Error} If DEVFLOW_DIR is invalid (not absolute, outside home)
|
|
20
|
+
*/
|
|
21
|
+
export declare function getDevFlowDirectory(): string;
|
|
22
|
+
/**
|
|
23
|
+
* Get installation paths based on scope (async, non-blocking)
|
|
24
|
+
* @param scope - 'user' or 'local'
|
|
25
|
+
* @returns Object with claudeDir and devflowDir
|
|
26
|
+
* @throws {Error} If local scope selected but not in a git repository
|
|
27
|
+
*/
|
|
28
|
+
export declare function getInstallationPaths(scope: 'user' | 'local'): Promise<{
|
|
29
|
+
claudeDir: string;
|
|
30
|
+
devflowDir: string;
|
|
31
|
+
}>;
|
|
32
|
+
//# sourceMappingURL=paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/cli/utils/paths.ts"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAMzC;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,MAAM,CAkB3C;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAkB5C;AAED;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAiBtH"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { homedir } from 'os';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { getGitRoot } from './git.js';
|
|
4
|
+
/**
|
|
5
|
+
* Get home directory with proper fallback and validation
|
|
6
|
+
* Priority: process.env.HOME > os.homedir()
|
|
7
|
+
*
|
|
8
|
+
* @throws {Error} If unable to determine home directory
|
|
9
|
+
*/
|
|
10
|
+
export function getHomeDirectory() {
|
|
11
|
+
const home = process.env.HOME || homedir();
|
|
12
|
+
if (!home) {
|
|
13
|
+
throw new Error('Unable to determine home directory. Set HOME environment variable.');
|
|
14
|
+
}
|
|
15
|
+
return home;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get Claude Code directory with environment variable override support
|
|
19
|
+
* Priority: CLAUDE_CODE_DIR env var > ~/.claude
|
|
20
|
+
*
|
|
21
|
+
* @throws {Error} If CLAUDE_CODE_DIR is invalid (not absolute, outside home)
|
|
22
|
+
*/
|
|
23
|
+
export function getClaudeDirectory() {
|
|
24
|
+
if (process.env.CLAUDE_CODE_DIR) {
|
|
25
|
+
const customDir = process.env.CLAUDE_CODE_DIR;
|
|
26
|
+
// Validate path is absolute
|
|
27
|
+
if (!path.isAbsolute(customDir)) {
|
|
28
|
+
throw new Error('CLAUDE_CODE_DIR must be an absolute path');
|
|
29
|
+
}
|
|
30
|
+
// Warn if outside home directory (security best practice)
|
|
31
|
+
const home = getHomeDirectory();
|
|
32
|
+
if (!customDir.startsWith(home)) {
|
|
33
|
+
console.warn('โ ๏ธ CLAUDE_CODE_DIR is outside home directory. Ensure this is intentional.');
|
|
34
|
+
}
|
|
35
|
+
return customDir;
|
|
36
|
+
}
|
|
37
|
+
return path.join(getHomeDirectory(), '.claude');
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get DevFlow directory with environment variable override support
|
|
41
|
+
* Priority: DEVFLOW_DIR env var > ~/.devflow
|
|
42
|
+
*
|
|
43
|
+
* @throws {Error} If DEVFLOW_DIR is invalid (not absolute, outside home)
|
|
44
|
+
*/
|
|
45
|
+
export function getDevFlowDirectory() {
|
|
46
|
+
if (process.env.DEVFLOW_DIR) {
|
|
47
|
+
const customDir = process.env.DEVFLOW_DIR;
|
|
48
|
+
// Validate path is absolute
|
|
49
|
+
if (!path.isAbsolute(customDir)) {
|
|
50
|
+
throw new Error('DEVFLOW_DIR must be an absolute path');
|
|
51
|
+
}
|
|
52
|
+
// Warn if outside home directory (security best practice)
|
|
53
|
+
const home = getHomeDirectory();
|
|
54
|
+
if (!customDir.startsWith(home)) {
|
|
55
|
+
console.warn('โ ๏ธ DEVFLOW_DIR is outside home directory. Ensure this is intentional.');
|
|
56
|
+
}
|
|
57
|
+
return customDir;
|
|
58
|
+
}
|
|
59
|
+
return path.join(getHomeDirectory(), '.devflow');
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get installation paths based on scope (async, non-blocking)
|
|
63
|
+
* @param scope - 'user' or 'local'
|
|
64
|
+
* @returns Object with claudeDir and devflowDir
|
|
65
|
+
* @throws {Error} If local scope selected but not in a git repository
|
|
66
|
+
*/
|
|
67
|
+
export async function getInstallationPaths(scope) {
|
|
68
|
+
if (scope === 'user') {
|
|
69
|
+
return {
|
|
70
|
+
claudeDir: getClaudeDirectory(),
|
|
71
|
+
devflowDir: getDevFlowDirectory()
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Local scope - install to git repository root
|
|
76
|
+
const gitRoot = await getGitRoot();
|
|
77
|
+
if (!gitRoot) {
|
|
78
|
+
throw new Error('Local scope requires a git repository. Run "git init" first or use --scope user');
|
|
79
|
+
}
|
|
80
|
+
return {
|
|
81
|
+
claudeDir: path.join(gitRoot, '.claude'),
|
|
82
|
+
devflowDir: path.join(gitRoot, '.devflow')
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/cli/utils/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;IAC3C,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAC;IACxF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB;IAChC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;QAE9C,4BAA4B;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QAED,0DAA0D;QAC1D,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,4EAA4E,CAAC,CAAC;QAC7F,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,SAAS,CAAC,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC;QAC5B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC;QAE1C,4BAA4B;QAC5B,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,0DAA0D;QAC1D,MAAM,IAAI,GAAG,gBAAgB,EAAE,CAAC;QAChC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YAChC,OAAO,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;QACzF,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,EAAE,UAAU,CAAC,CAAC;AACnD,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,KAAuB;IAChE,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO;YACL,SAAS,EAAE,kBAAkB,EAAE;YAC/B,UAAU,EAAE,mBAAmB,EAAE;SAClC,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,+CAA+C;QAC/C,MAAM,OAAO,GAAG,MAAM,UAAU,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,iFAAiF,CAAC,CAAC;QACrG,CAAC;QACD,OAAO;YACL,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC;YACxC,UAAU,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;SAC3C,CAAC;IACJ,CAAC;AACH,CAAC"}
|
package/package.json
CHANGED