wogiflow 1.9.9 → 2.0.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/.claude/settings.json +45 -12
- package/.workflow/lib/assumption-detector.js +4 -481
- package/.workflow/lib/config-substitution.js +4 -389
- package/.workflow/lib/failure-categories.js +4 -478
- package/lib/commands/login.js +6 -6
- package/lib/commands/logout.js +1 -1
- package/lib/commands/team-connection.js +8 -8
- package/lib/installer.js +19 -20
- package/lib/release-channel.js +2 -2
- package/lib/skill-registry.js +4 -4
- package/lib/upgrader.js +4 -3
- package/lib/utils.js +4 -4
- package/package.json +8 -1
- package/scripts/flow +3 -0
- package/scripts/flow-adaptive-learning.js +19 -36
- package/scripts/flow-aggregate.js +5 -5
- package/scripts/flow-api-index.js +3 -3
- package/scripts/flow-assumption-detector.js +483 -0
- package/scripts/flow-audit.js +6 -6
- package/scripts/flow-auto-context.js +18 -17
- package/scripts/flow-auto-learn.js +5 -5
- package/scripts/flow-background.js +6 -7
- package/scripts/flow-best-of-n.js +1 -1
- package/scripts/flow-bridge-state.js +7 -7
- package/scripts/flow-bridge.js +8 -7
- package/scripts/flow-bug.js +3 -3
- package/scripts/flow-bulk-loop.js +21 -24
- package/scripts/flow-bulk-orchestrator.js +28 -28
- package/scripts/flow-capture.js +8 -8
- package/scripts/flow-cascade-completion.js +512 -0
- package/scripts/flow-cascade.js +2 -2
- package/scripts/flow-checkpoint.js +13 -12
- package/scripts/flow-clarifying-questions.js +4 -4
- package/scripts/flow-cli.js +9 -8
- package/scripts/flow-code-intelligence.js +11 -17
- package/scripts/flow-community-sync.js +2 -2
- package/scripts/flow-community.js +36 -36
- package/scripts/flow-config-defaults.js +14 -6
- package/scripts/flow-config-interactive.js +3 -3
- package/scripts/flow-config-loader.js +30 -61
- package/scripts/flow-config-set.js +2 -2
- package/scripts/flow-config-substitution.js +392 -0
- package/scripts/flow-conflict-resolver.js +7 -68
- package/scripts/flow-consistency-check.js +2 -2
- package/scripts/flow-constants.js +34 -30
- package/scripts/flow-context-compact/expander.js +3 -3
- package/scripts/flow-context-compact/index.js +4 -4
- package/scripts/flow-context-compact/section-extractor.js +1 -1
- package/scripts/flow-context-compact/summary-tree.js +6 -6
- package/scripts/flow-context-estimator.js +33 -2
- package/scripts/flow-context-gatherer.js +2 -2
- package/scripts/flow-context-generator.js +3 -3
- package/scripts/flow-context-init.js +11 -9
- package/scripts/flow-context-monitor.js +5 -5
- package/scripts/flow-context-orchestrator.js +1 -1
- package/scripts/flow-context-scoring.js +8 -8
- package/scripts/flow-correct.js +6 -6
- package/scripts/flow-correction-detector.js +3 -3
- package/scripts/flow-damage-control.js +14 -3
- package/scripts/flow-decision-tracker.js +2 -2
- package/scripts/flow-decisions-merge.js +4 -4
- package/scripts/flow-diff.js +16 -11
- package/scripts/flow-done.js +135 -558
- package/scripts/flow-durable-session.js +7 -6
- package/scripts/flow-entropy-monitor.js +4 -3
- package/scripts/flow-epics.js +4 -5
- package/scripts/flow-error-recovery.js +2 -2
- package/scripts/flow-eval-judge.js +3 -3
- package/scripts/flow-eval.js +8 -8
- package/scripts/flow-export-profile +3 -3
- package/scripts/flow-export-scanner.js +7 -7
- package/scripts/flow-extraction-review.js +3 -12
- package/scripts/flow-failure-categories.js +480 -0
- package/scripts/flow-failure-learning.js +3 -3
- package/scripts/flow-feature.js +3 -3
- package/scripts/flow-figma-confirm.js +11 -7
- package/scripts/flow-figma-extract.js +3 -3
- package/scripts/flow-figma-generate.js +17 -13
- package/scripts/flow-figma-index.js +18 -23
- package/scripts/flow-figma-match.js +6 -5
- package/scripts/flow-figma-mcp-server.js +6 -13
- package/scripts/flow-figma-orchestrator.js +2 -2
- package/scripts/flow-figma-registry.js +2 -2
- package/scripts/flow-function-index.js +3 -3
- package/scripts/flow-gate-confidence.js +2 -2
- package/scripts/flow-gitignore.js +3 -3
- package/scripts/flow-guided-edit.js +13 -21
- package/scripts/flow-health.js +111 -100
- package/scripts/flow-hooks-install.js +3 -3
- package/scripts/flow-hooks.js +25 -27
- package/scripts/flow-http-client.js +2 -2
- package/scripts/flow-hybrid-detect.js +2 -2
- package/scripts/flow-hybrid-interactive.js +7 -6
- package/scripts/flow-hybrid-test.js +6 -6
- package/scripts/flow-hypothesis-generator.js +14 -13
- package/scripts/flow-import-profile +1 -1
- package/scripts/flow-instruction-richness.js +8 -8
- package/scripts/flow-io.js +16 -16
- package/scripts/flow-knowledge-router.js +12 -11
- package/scripts/flow-knowledge-sync.js +14 -20
- package/scripts/flow-links.js +13 -20
- package/scripts/flow-log-manager.js +5 -5
- package/scripts/flow-long-input-chunking.js +32 -56
- package/scripts/flow-long-input-cli.js +3066 -0
- package/scripts/flow-long-input-complexity.js +422 -0
- package/scripts/flow-long-input-constants.js +445 -0
- package/scripts/flow-long-input-detection.js +757 -0
- package/scripts/flow-long-input-stories.js +2 -2
- package/scripts/flow-long-input-voice.js +390 -0
- package/scripts/flow-long-input.js +117 -4845
- package/scripts/flow-loop-retry-learning.js +54 -66
- package/scripts/flow-lsp.js +3 -3
- package/scripts/flow-mcp-docs.js +8 -10
- package/scripts/flow-memory-blocks.js +3 -3
- package/scripts/flow-memory-compactor.js +4 -10
- package/scripts/flow-memory-db.js +6 -5
- package/scripts/flow-memory-sync.js +5 -14
- package/scripts/flow-metrics.js +8 -12
- package/scripts/flow-migrate.js +11 -17
- package/scripts/flow-model-adapter.js +8 -16
- package/scripts/flow-model-caller.js +1 -1
- package/scripts/flow-model-config.js +9 -9
- package/scripts/flow-model-profile.js +3 -3
- package/scripts/flow-model-router.js +1 -1
- package/scripts/flow-model-types.js +2 -2
- package/scripts/flow-models.js +2 -2
- package/scripts/flow-morning.js +10 -10
- package/scripts/flow-multi-approach.js +8 -7
- package/scripts/flow-orchestrate-context.js +793 -0
- package/scripts/flow-orchestrate-llm.js +2 -2
- package/scripts/flow-orchestrate-rollback.js +108 -0
- package/scripts/flow-orchestrate-state.js +323 -0
- package/scripts/flow-orchestrate-templates.js +253 -0
- package/scripts/flow-orchestrate-validation.js +3 -3
- package/scripts/flow-orchestrate-validator.js +176 -0
- package/scripts/flow-orchestrate.js +323 -1848
- package/scripts/flow-output.js +9 -0
- package/scripts/flow-parallel.js +6 -6
- package/scripts/flow-paths.js +26 -9
- package/scripts/flow-pattern-enforcer.js +4 -4
- package/scripts/flow-pattern-extractor.js +23 -34
- package/scripts/flow-peer-review.js +4 -4
- package/scripts/flow-permissions.js +8 -10
- package/scripts/flow-phased-task.js +2 -2
- package/scripts/flow-plan.js +3 -3
- package/scripts/flow-plugin-registry.js +2 -2
- package/scripts/flow-prd-manager.js +2 -2
- package/scripts/flow-proactive-compact.js +1 -1
- package/scripts/flow-product-scanner.js +2 -2
- package/scripts/flow-progress.js +1 -1
- package/scripts/flow-project-analyzer.js +10 -10
- package/scripts/flow-prompt-capture.js +3 -3
- package/scripts/flow-prompt-composer.js +4 -4
- package/scripts/flow-prompt-template.js +3 -3
- package/scripts/flow-providers.js +23 -22
- package/scripts/flow-queue.js +10 -10
- package/scripts/flow-ready.js +4 -7
- package/scripts/flow-registry-manager.js +3 -3
- package/scripts/flow-regression.js +15 -14
- package/scripts/flow-research-protocol.js +2 -2
- package/scripts/flow-response-parser.js +4 -4
- package/scripts/flow-resume.js +6 -6
- package/scripts/flow-review-passes/index.js +11 -8
- package/scripts/flow-review-passes/integration.js +1 -1
- package/scripts/flow-review-passes/logic.js +1 -1
- package/scripts/flow-review-passes/security.js +11 -32
- package/scripts/flow-review-passes/structure.js +2 -2
- package/scripts/flow-review.js +10 -13
- package/scripts/flow-revision-tracker.js +2 -2
- package/scripts/flow-roadmap.js +24 -23
- package/scripts/flow-rules-sync.js +2 -2
- package/scripts/flow-run-trace.js +24 -38
- package/scripts/flow-safety.js +7 -6
- package/scripts/flow-scanner-base.js +3 -3
- package/scripts/flow-scenario-engine.js +55 -54
- package/scripts/flow-script-resolver.js +8 -22
- package/scripts/flow-section-index.js +5 -5
- package/scripts/flow-security.js +148 -4
- package/scripts/flow-semantic-match.js +2 -2
- package/scripts/flow-session-end.js +22 -22
- package/scripts/flow-session-learning.js +3 -3
- package/scripts/flow-session-state.js +2 -2
- package/scripts/flow-setup-hooks.js +13 -16
- package/scripts/flow-skill-create.js +11 -8
- package/scripts/flow-skill-freshness.js +3 -3
- package/scripts/flow-skill-generator.js +27 -24
- package/scripts/flow-skill-learn.js +4 -4
- package/scripts/flow-skill-matcher.js +4 -3
- package/scripts/flow-solution-optimizer.js +5 -11
- package/scripts/flow-spec-generator.js +19 -22
- package/scripts/flow-spec-verifier.js +5 -5
- package/scripts/flow-stack-wizard.js +12 -21
- package/scripts/flow-standards-checker.js +3 -3
- package/scripts/flow-standards-gate.js +2 -2
- package/scripts/flow-standards-learner.js +4 -4
- package/scripts/flow-start.js +14 -13
- package/scripts/flow-state-cleanup.js +2 -2
- package/scripts/flow-stats-collector.js +2 -2
- package/scripts/flow-status.js +5 -6
- package/scripts/flow-statusline-setup.js +13 -11
- package/scripts/flow-step-changelog.js +2 -2
- package/scripts/flow-step-comments.js +2 -2
- package/scripts/flow-step-complexity.js +2 -2
- package/scripts/flow-step-coverage.js +9 -7
- package/scripts/flow-step-knowledge.js +2 -2
- package/scripts/flow-step-pr-tests.js +4 -8
- package/scripts/flow-step-regression.js +2 -2
- package/scripts/flow-step-review.js +2 -2
- package/scripts/flow-step-security.js +9 -14
- package/scripts/flow-step-silent-failures.js +2 -2
- package/scripts/flow-step-simplifier.js +2 -2
- package/scripts/flow-story.js +12 -11
- package/scripts/flow-strict-adherence.js +2 -2
- package/scripts/flow-suspend.js +2 -2
- package/scripts/flow-sync-anonymizer.js +1 -1
- package/scripts/flow-task-analyzer.js +2 -2
- package/scripts/flow-task-checkpoint.js +9 -10
- package/scripts/flow-task-classifier.js +2 -2
- package/scripts/flow-task-completion-summary.js +18 -18
- package/scripts/flow-task-enforcer.js +6 -6
- package/scripts/flow-tech-debt.js +7 -6
- package/scripts/flow-template-extractor.js +10 -18
- package/scripts/flow-templates.js +7 -12
- package/scripts/flow-test-api.js +3 -3
- package/scripts/flow-test-discovery.js +6 -7
- package/scripts/flow-test-generate.js +2 -2
- package/scripts/flow-test-integrity.js +2 -2
- package/scripts/flow-test-ui.js +5 -5
- package/scripts/flow-testing-deps.js +3 -3
- package/scripts/flow-tiered-learning.js +2 -2
- package/scripts/flow-todowrite-sync.js +2 -2
- package/scripts/flow-utils.js +32 -473
- package/scripts/flow-verification-profile.js +32 -35
- package/scripts/flow-verify.js +39 -50
- package/scripts/flow-version-check.js +17 -27
- package/scripts/flow-webmcp-generator.js +11 -6
- package/scripts/flow-wiring-verifier.js +3 -3
- package/scripts/flow-workflow-steps.js +2 -2
- package/scripts/flow-workflow.js +13 -11
- package/scripts/flow-worktree.js +11 -11
- package/scripts/hooks/adapters/claude-code.js +37 -5
- package/scripts/hooks/core/component-check.js +5 -6
- package/scripts/hooks/core/config-change.js +4 -4
- package/scripts/hooks/core/instructions-loaded.js +9 -9
- package/scripts/hooks/core/loop-check.js +6 -6
- package/scripts/hooks/core/observation-capture.js +2 -2
- package/scripts/hooks/core/phase-gate.js +2 -2
- package/scripts/hooks/core/post-compact.js +143 -0
- package/scripts/hooks/core/research-gate.js +2 -2
- package/scripts/hooks/core/routing-gate.js +7 -7
- package/scripts/hooks/core/scope-gate.js +2 -17
- package/scripts/hooks/core/session-context.js +16 -16
- package/scripts/hooks/core/session-end.js +2 -2
- package/scripts/hooks/core/setup-check.js +2 -2
- package/scripts/hooks/core/task-completed.js +8 -8
- package/scripts/hooks/core/task-gate.js +5 -5
- package/scripts/hooks/core/validation.js +5 -5
- package/scripts/hooks/core/worktree-lifecycle.js +3 -3
- package/scripts/hooks/entry/claude-code/config-change.js +3 -8
- package/scripts/hooks/entry/claude-code/instructions-loaded.js +3 -12
- package/scripts/hooks/entry/claude-code/post-compact.js +45 -0
- package/scripts/hooks/entry/claude-code/post-tool-use.js +1 -1
- package/scripts/hooks/entry/claude-code/pre-tool-use.js +65 -1
- package/scripts/hooks/entry/claude-code/session-end.js +3 -7
- package/scripts/hooks/entry/claude-code/session-start.js +8 -4
- package/scripts/hooks/entry/claude-code/setup.js +3 -7
- package/scripts/hooks/entry/claude-code/stop.js +3 -17
- package/scripts/hooks/entry/claude-code/task-completed.js +3 -8
- package/scripts/hooks/entry/claude-code/user-prompt-submit.js +6 -19
- package/scripts/hooks/entry/claude-code/worktree-create.js +3 -7
- package/scripts/hooks/entry/claude-code/worktree-remove.js +3 -7
- package/scripts/hooks/git/post-commit.js +5 -4
- package/scripts/postinstall.js +7 -3
- package/scripts/preuninstall.js +2 -2
- package/scripts/registries/component-registry.js +4 -3
- package/scripts/registries/schema-registry.js +5 -5
- package/scripts/registries/service-registry.js +6 -6
|
@@ -1,389 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
* - {env:VAR_NAME} - Environment variable substitution
|
|
6
|
-
* - {file:path/to/file} - File content substitution
|
|
7
|
-
*
|
|
8
|
-
* Features:
|
|
9
|
-
* - Tilde expansion (~/.secrets → /home/user/.secrets)
|
|
10
|
-
* - Nested object/array processing
|
|
11
|
-
* - Graceful handling of missing values
|
|
12
|
-
* - Warning logging for unresolved placeholders
|
|
13
|
-
*
|
|
14
|
-
* Usage:
|
|
15
|
-
* const { substituteConfig } = require('./.workflow/lib/config-substitution');
|
|
16
|
-
* const resolvedConfig = substituteConfig(rawConfig);
|
|
17
|
-
*/
|
|
18
|
-
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
const path = require('path');
|
|
21
|
-
const os = require('os');
|
|
22
|
-
|
|
23
|
-
// ============================================================
|
|
24
|
-
// Patterns
|
|
25
|
-
// ============================================================
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Substitution patterns
|
|
29
|
-
*/
|
|
30
|
-
const PATTERNS = {
|
|
31
|
-
env: /\{env:([^}]+)\}/g, // {env:VAR_NAME}
|
|
32
|
-
file: /\{file:([^}]+)\}/g // {file:path/to/file}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Check if a value contains substitution patterns
|
|
37
|
-
* @param {string} value - Value to check
|
|
38
|
-
* @returns {boolean}
|
|
39
|
-
*/
|
|
40
|
-
function hasSubstitutionPattern(value) {
|
|
41
|
-
if (typeof value !== 'string') return false;
|
|
42
|
-
return PATTERNS.env.test(value) || PATTERNS.file.test(value);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// ============================================================
|
|
46
|
-
// Path Utilities
|
|
47
|
-
// ============================================================
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Expand tilde (~) to user's home directory
|
|
51
|
-
* @param {string} filePath - Path that may contain ~
|
|
52
|
-
* @returns {string} Expanded path
|
|
53
|
-
*/
|
|
54
|
-
function expandTilde(filePath) {
|
|
55
|
-
if (!filePath || typeof filePath !== 'string') return filePath;
|
|
56
|
-
|
|
57
|
-
if (filePath.startsWith('~/')) {
|
|
58
|
-
return path.join(os.homedir(), filePath.slice(2));
|
|
59
|
-
}
|
|
60
|
-
if (filePath === '~') {
|
|
61
|
-
return os.homedir();
|
|
62
|
-
}
|
|
63
|
-
return filePath;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/**
|
|
67
|
-
* Resolve a file path (handles tilde and relative paths)
|
|
68
|
-
* @param {string} filePath - Path to resolve
|
|
69
|
-
* @param {string} basePath - Base path for relative paths
|
|
70
|
-
* @returns {string} Resolved absolute path
|
|
71
|
-
*/
|
|
72
|
-
function resolvePath(filePath, basePath = process.cwd()) {
|
|
73
|
-
const expanded = expandTilde(filePath);
|
|
74
|
-
if (path.isAbsolute(expanded)) {
|
|
75
|
-
return expanded;
|
|
76
|
-
}
|
|
77
|
-
return path.resolve(basePath, expanded);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// ============================================================
|
|
81
|
-
// Substitution Functions
|
|
82
|
-
// ============================================================
|
|
83
|
-
|
|
84
|
-
/**
|
|
85
|
-
* Substitute environment variable pattern
|
|
86
|
-
* @param {string} value - String containing {env:VAR} patterns
|
|
87
|
-
* @param {Object} options - Options
|
|
88
|
-
* @returns {Object} Result with value and warnings
|
|
89
|
-
*/
|
|
90
|
-
function substituteEnvVars(value, options = {}) {
|
|
91
|
-
const { logWarnings = true } = options;
|
|
92
|
-
const warnings = [];
|
|
93
|
-
|
|
94
|
-
// Reset regex lastIndex
|
|
95
|
-
PATTERNS.env.lastIndex = 0;
|
|
96
|
-
|
|
97
|
-
const result = value.replace(PATTERNS.env, (match, varName) => {
|
|
98
|
-
const envValue = process.env[varName];
|
|
99
|
-
|
|
100
|
-
if (envValue !== undefined) {
|
|
101
|
-
return envValue;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Env var not set - keep placeholder and warn
|
|
105
|
-
if (logWarnings) {
|
|
106
|
-
warnings.push({
|
|
107
|
-
type: 'env',
|
|
108
|
-
pattern: match,
|
|
109
|
-
variable: varName,
|
|
110
|
-
message: `Environment variable '${varName}' is not set`
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
return match; // Keep original placeholder
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
return { value: result, warnings };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Substitute file content pattern
|
|
121
|
-
* @param {string} value - String containing {file:path} patterns
|
|
122
|
-
* @param {Object} options - Options
|
|
123
|
-
* @returns {Object} Result with value and warnings
|
|
124
|
-
*/
|
|
125
|
-
function substituteFileContents(value, options = {}) {
|
|
126
|
-
const { logWarnings = true, basePath = process.cwd() } = options;
|
|
127
|
-
const warnings = [];
|
|
128
|
-
|
|
129
|
-
// Reset regex lastIndex
|
|
130
|
-
PATTERNS.file.lastIndex = 0;
|
|
131
|
-
|
|
132
|
-
const result = value.replace(PATTERNS.file, (match, filePath) => {
|
|
133
|
-
const resolvedPath = resolvePath(filePath.trim(), basePath);
|
|
134
|
-
|
|
135
|
-
// Security: validate path is within project or user's home directory
|
|
136
|
-
const homeDir = os.homedir();
|
|
137
|
-
const absResolved = path.resolve(resolvedPath);
|
|
138
|
-
const isWithinBase = absResolved.startsWith(path.resolve(basePath) + path.sep) || absResolved === path.resolve(basePath);
|
|
139
|
-
const isWithinHome = homeDir && absResolved.startsWith(homeDir + path.sep);
|
|
140
|
-
if (!isWithinBase && !isWithinHome) {
|
|
141
|
-
if (logWarnings) {
|
|
142
|
-
warnings.push({
|
|
143
|
-
type: 'file',
|
|
144
|
-
pattern: match,
|
|
145
|
-
path: filePath,
|
|
146
|
-
resolvedPath,
|
|
147
|
-
message: `File path outside allowed locations blocked: ${resolvedPath}`
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
return match; // Keep original placeholder
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
try {
|
|
154
|
-
if (fs.existsSync(resolvedPath)) {
|
|
155
|
-
const content = fs.readFileSync(resolvedPath, 'utf-8');
|
|
156
|
-
return content.trim(); // Trim whitespace from file contents
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// File doesn't exist - keep placeholder and warn
|
|
160
|
-
if (logWarnings) {
|
|
161
|
-
warnings.push({
|
|
162
|
-
type: 'file',
|
|
163
|
-
pattern: match,
|
|
164
|
-
path: filePath,
|
|
165
|
-
resolvedPath,
|
|
166
|
-
message: `File not found: ${resolvedPath}`
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
return match; // Keep original placeholder
|
|
170
|
-
} catch (err) {
|
|
171
|
-
if (logWarnings) {
|
|
172
|
-
warnings.push({
|
|
173
|
-
type: 'file',
|
|
174
|
-
pattern: match,
|
|
175
|
-
path: filePath,
|
|
176
|
-
resolvedPath,
|
|
177
|
-
message: `Error reading file: ${err.message}`
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
return match;
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
return { value: result, warnings };
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Substitute all patterns in a string value
|
|
189
|
-
* @param {string} value - String to process
|
|
190
|
-
* @param {Object} options - Options
|
|
191
|
-
* @returns {Object} Result with value and warnings
|
|
192
|
-
*/
|
|
193
|
-
function substituteString(value, options = {}) {
|
|
194
|
-
if (typeof value !== 'string') {
|
|
195
|
-
return { value, warnings: [] };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
const allWarnings = [];
|
|
199
|
-
|
|
200
|
-
// First pass: environment variables
|
|
201
|
-
let result = value;
|
|
202
|
-
const envResult = substituteEnvVars(result, options);
|
|
203
|
-
result = envResult.value;
|
|
204
|
-
allWarnings.push(...envResult.warnings);
|
|
205
|
-
|
|
206
|
-
// Second pass: file contents
|
|
207
|
-
const fileResult = substituteFileContents(result, options);
|
|
208
|
-
result = fileResult.value;
|
|
209
|
-
allWarnings.push(...fileResult.warnings);
|
|
210
|
-
|
|
211
|
-
return { value: result, warnings: allWarnings };
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// ============================================================
|
|
215
|
-
// Deep Substitution
|
|
216
|
-
// ============================================================
|
|
217
|
-
|
|
218
|
-
/**
|
|
219
|
-
* Recursively substitute patterns in an object/array
|
|
220
|
-
* @param {*} obj - Object, array, or value to process
|
|
221
|
-
* @param {Object} options - Options
|
|
222
|
-
* @param {string} path - Current path in object (for debugging)
|
|
223
|
-
* @returns {Object} Result with value and warnings
|
|
224
|
-
*/
|
|
225
|
-
function substituteDeep(obj, options = {}, currentPath = '') {
|
|
226
|
-
const allWarnings = [];
|
|
227
|
-
|
|
228
|
-
if (obj === null || obj === undefined) {
|
|
229
|
-
return { value: obj, warnings: [] };
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Handle arrays
|
|
233
|
-
if (Array.isArray(obj)) {
|
|
234
|
-
const result = obj.map((item, index) => {
|
|
235
|
-
const itemResult = substituteDeep(item, options, `${currentPath}[${index}]`);
|
|
236
|
-
allWarnings.push(...itemResult.warnings.map(w => ({
|
|
237
|
-
...w,
|
|
238
|
-
path: `${currentPath}[${index}]`
|
|
239
|
-
})));
|
|
240
|
-
return itemResult.value;
|
|
241
|
-
});
|
|
242
|
-
return { value: result, warnings: allWarnings };
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
// Handle objects
|
|
246
|
-
if (typeof obj === 'object') {
|
|
247
|
-
const result = {};
|
|
248
|
-
for (const [key, value] of Object.entries(obj)) {
|
|
249
|
-
const keyPath = currentPath ? `${currentPath}.${key}` : key;
|
|
250
|
-
const itemResult = substituteDeep(value, options, keyPath);
|
|
251
|
-
allWarnings.push(...itemResult.warnings.map(w => ({
|
|
252
|
-
...w,
|
|
253
|
-
path: keyPath
|
|
254
|
-
})));
|
|
255
|
-
result[key] = itemResult.value;
|
|
256
|
-
}
|
|
257
|
-
return { value: result, warnings: allWarnings };
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
// Handle strings
|
|
261
|
-
if (typeof obj === 'string') {
|
|
262
|
-
const strResult = substituteString(obj, options);
|
|
263
|
-
return {
|
|
264
|
-
value: strResult.value,
|
|
265
|
-
warnings: strResult.warnings.map(w => ({
|
|
266
|
-
...w,
|
|
267
|
-
path: currentPath
|
|
268
|
-
}))
|
|
269
|
-
};
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Other primitives - return as-is
|
|
273
|
-
return { value: obj, warnings: [] };
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// ============================================================
|
|
277
|
-
// Main API
|
|
278
|
-
// ============================================================
|
|
279
|
-
|
|
280
|
-
/**
|
|
281
|
-
* Substitute all patterns in a config object
|
|
282
|
-
* @param {Object} config - Config object to process
|
|
283
|
-
* @param {Object} options - Options
|
|
284
|
-
* @param {boolean} options.logWarnings - Whether to log warnings (default: true)
|
|
285
|
-
* @param {boolean} options.printWarnings - Whether to print warnings to console (default: false)
|
|
286
|
-
* @param {string} options.basePath - Base path for relative file paths
|
|
287
|
-
* @returns {Object} Result with value and warnings array
|
|
288
|
-
*/
|
|
289
|
-
function substituteConfig(config, options = {}) {
|
|
290
|
-
const { printWarnings = false, logWarnings = true, basePath } = options;
|
|
291
|
-
|
|
292
|
-
const result = substituteDeep(config, { logWarnings, basePath });
|
|
293
|
-
|
|
294
|
-
// Print warnings to console if requested
|
|
295
|
-
if (printWarnings && result.warnings.length > 0) {
|
|
296
|
-
console.warn('\n⚠️ Config substitution warnings:');
|
|
297
|
-
for (const warning of result.warnings) {
|
|
298
|
-
const pathInfo = warning.path ? ` at '${warning.path}'` : '';
|
|
299
|
-
console.warn(` - ${warning.message}${pathInfo}`);
|
|
300
|
-
}
|
|
301
|
-
console.warn('');
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
return result;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Check if a config has unresolved substitution patterns
|
|
309
|
-
* @param {Object} config - Config object to check
|
|
310
|
-
* @returns {Object} Result with hasUnresolved boolean and patterns array
|
|
311
|
-
*/
|
|
312
|
-
function checkUnresolvedPatterns(config) {
|
|
313
|
-
const configStr = JSON.stringify(config);
|
|
314
|
-
const unresolvedEnv = [];
|
|
315
|
-
const unresolvedFile = [];
|
|
316
|
-
|
|
317
|
-
// Check for env patterns
|
|
318
|
-
PATTERNS.env.lastIndex = 0;
|
|
319
|
-
let match;
|
|
320
|
-
while ((match = PATTERNS.env.exec(configStr)) !== null) {
|
|
321
|
-
unresolvedEnv.push({ pattern: match[0], variable: match[1] });
|
|
322
|
-
}
|
|
323
|
-
|
|
324
|
-
// Check for file patterns
|
|
325
|
-
PATTERNS.file.lastIndex = 0;
|
|
326
|
-
while ((match = PATTERNS.file.exec(configStr)) !== null) {
|
|
327
|
-
unresolvedFile.push({ pattern: match[0], path: match[1] });
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
return {
|
|
331
|
-
hasUnresolved: unresolvedEnv.length > 0 || unresolvedFile.length > 0,
|
|
332
|
-
env: unresolvedEnv,
|
|
333
|
-
file: unresolvedFile
|
|
334
|
-
};
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
/**
|
|
338
|
-
* Get a list of all substitution patterns used in a config
|
|
339
|
-
* @param {Object} config - Config object to scan
|
|
340
|
-
* @returns {Object} Object with env and file pattern lists
|
|
341
|
-
*/
|
|
342
|
-
function getUsedPatterns(config) {
|
|
343
|
-
const configStr = JSON.stringify(config);
|
|
344
|
-
const envPatterns = new Set();
|
|
345
|
-
const filePatterns = new Set();
|
|
346
|
-
|
|
347
|
-
// Find env patterns
|
|
348
|
-
PATTERNS.env.lastIndex = 0;
|
|
349
|
-
let match;
|
|
350
|
-
while ((match = PATTERNS.env.exec(configStr)) !== null) {
|
|
351
|
-
envPatterns.add(match[1]);
|
|
352
|
-
}
|
|
353
|
-
|
|
354
|
-
// Find file patterns
|
|
355
|
-
PATTERNS.file.lastIndex = 0;
|
|
356
|
-
while ((match = PATTERNS.file.exec(configStr)) !== null) {
|
|
357
|
-
filePatterns.add(match[1]);
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
return {
|
|
361
|
-
env: Array.from(envPatterns),
|
|
362
|
-
file: Array.from(filePatterns)
|
|
363
|
-
};
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// ============================================================
|
|
367
|
-
// Exports
|
|
368
|
-
// ============================================================
|
|
369
|
-
|
|
370
|
-
module.exports = {
|
|
371
|
-
// Main API
|
|
372
|
-
substituteConfig,
|
|
373
|
-
checkUnresolvedPatterns,
|
|
374
|
-
getUsedPatterns,
|
|
375
|
-
|
|
376
|
-
// Lower-level functions
|
|
377
|
-
substituteString,
|
|
378
|
-
substituteEnvVars,
|
|
379
|
-
substituteFileContents,
|
|
380
|
-
substituteDeep,
|
|
381
|
-
|
|
382
|
-
// Utilities
|
|
383
|
-
expandTilde,
|
|
384
|
-
resolvePath,
|
|
385
|
-
hasSubstitutionPattern,
|
|
386
|
-
|
|
387
|
-
// Constants
|
|
388
|
-
PATTERNS
|
|
389
|
-
};
|
|
1
|
+
// DEPRECATED: This file has been moved to scripts/flow-config-substitution.js
|
|
2
|
+
// This copy is kept for backward compatibility with existing installations.
|
|
3
|
+
// It re-exports from the new location.
|
|
4
|
+
module.exports = require('../../scripts/flow-config-substitution');
|