pipecraft 0.0.0-releaseit
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.local.json +35 -0
- package/.github/actions/calculate-version/action.yml +106 -0
- package/.github/actions/create-pr/action.yml +122 -0
- package/.github/actions/create-release/action.yml +74 -0
- package/.github/actions/create-tag/action.yml +94 -0
- package/.github/actions/detect-changes/action.yml +62 -0
- package/.github/actions/manage-branch/action.yml +113 -0
- package/.github/actions/promote-branch/action.yml +352 -0
- package/.github/example/workflows/job.analyze.code.yml +26 -0
- package/.github/example/workflows/job.analyze.docker.yml +32 -0
- package/.github/example/workflows/job.app.api.deploy.yml +127 -0
- package/.github/example/workflows/job.app.api.test.yml +102 -0
- package/.github/example/workflows/job.app.docs.deploy.yml +40 -0
- package/.github/example/workflows/job.app.docs.test.yml +50 -0
- package/.github/example/workflows/job.app.web.deploy.yml +96 -0
- package/.github/example/workflows/job.app.web.test.yml +49 -0
- package/.github/example/workflows/job.changes.yml +82 -0
- package/.github/example/workflows/job.create-pr.yml +96 -0
- package/.github/example/workflows/job.env-check.yml +43 -0
- package/.github/example/workflows/job.fast-forward.yml +103 -0
- package/.github/example/workflows/job.lint.yml +64 -0
- package/.github/example/workflows/job.pr-name.yml +70 -0
- package/.github/example/workflows/job.pr-squash-name.yml +27 -0
- package/.github/example/workflows/job.tag.yml +38 -0
- package/.github/example/workflows/job.version.yml +99 -0
- package/.github/example/workflows/lib.plugin-base.publish.yml +59 -0
- package/.github/example/workflows/pipe.yml +178 -0
- package/.github/example/workflows/scripts/fastforward.sh +51 -0
- package/.github/example/workflows/scripts/pipe-cleaner.sh +70 -0
- package/.github/scripts/fastforward.sh +51 -0
- package/.github/scripts/pipe-cleaner.sh +70 -0
- package/.github/workflows/pipeline.yml +220 -0
- package/.github/workflows/pr-title-check.yml +70 -0
- package/.github/workflows/publish.yml +39 -0
- package/.pipecraftrc.json +78 -0
- package/.release-it.cjs +71 -0
- package/PIPELINE_TESTING_PLAN.md +499 -0
- package/README.md +1101 -0
- package/TRUNK_FLOW_PLAN.md +401 -0
- package/assets/logo_banner.png +0 -0
- package/assets/logo_banner.webp +0 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +364 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/generators/init.tpl.d.ts +3 -0
- package/dist/generators/init.tpl.d.ts.map +1 -0
- package/dist/generators/init.tpl.js +117 -0
- package/dist/generators/init.tpl.js.map +1 -0
- package/dist/generators/workflows.tpl.d.ts +7 -0
- package/dist/generators/workflows.tpl.d.ts.map +1 -0
- package/dist/generators/workflows.tpl.js +73 -0
- package/dist/generators/workflows.tpl.js.map +1 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/calculate-version.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/calculate-version.yml.tpl.js +122 -0
- package/dist/templates/actions/calculate-version.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/create-pr.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-pr.yml.tpl.js +145 -0
- package/dist/templates/actions/create-pr.yml.tpl.js.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/create-tag.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/create-tag.yml.tpl.js +111 -0
- package/dist/templates/actions/create-tag.yml.tpl.js.map +1 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/detect-changes.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/detect-changes.yml.tpl.js +79 -0
- package/dist/templates/actions/detect-changes.yml.tpl.js.map +1 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/manage-branch.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/manage-branch.yml.tpl.js +130 -0
- package/dist/templates/actions/manage-branch.yml.tpl.js.map +1 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts +3 -0
- package/dist/templates/actions/promote-branch.yml.tpl.d.ts.map +1 -0
- package/dist/templates/actions/promote-branch.yml.tpl.js +362 -0
- package/dist/templates/actions/promote-branch.yml.tpl.js.map +1 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts +16 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.d.ts.map +1 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js +652 -0
- package/dist/templates/workflows/pipeline-path-based.yml.tpl.js.map +1 -0
- package/dist/types/index.d.ts +63 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/ast-path-operations.d.ts +287 -0
- package/dist/utils/ast-path-operations.d.ts.map +1 -0
- package/dist/utils/ast-path-operations.js +419 -0
- package/dist/utils/ast-path-operations.js.map +1 -0
- package/dist/utils/config.d.ts +3 -0
- package/dist/utils/config.d.ts.map +1 -0
- package/dist/utils/config.js +49 -0
- package/dist/utils/config.js.map +1 -0
- package/dist/utils/github-setup.d.ts +74 -0
- package/dist/utils/github-setup.d.ts.map +1 -0
- package/dist/utils/github-setup.js +418 -0
- package/dist/utils/github-setup.js.map +1 -0
- package/dist/utils/idempotency.d.ts +47 -0
- package/dist/utils/idempotency.d.ts.map +1 -0
- package/dist/utils/idempotency.js +176 -0
- package/dist/utils/idempotency.js.map +1 -0
- package/dist/utils/preflight.d.ts +55 -0
- package/dist/utils/preflight.d.ts.map +1 -0
- package/dist/utils/preflight.js +261 -0
- package/dist/utils/preflight.js.map +1 -0
- package/dist/utils/versioning.d.ts +41 -0
- package/dist/utils/versioning.d.ts.map +1 -0
- package/dist/utils/versioning.js +219 -0
- package/dist/utils/versioning.js.map +1 -0
- package/docs/USER_JOURNEY_ERRORS.md +352 -0
- package/eslint.config.js +77 -0
- package/examples/basic-config.json +41 -0
- package/examples/monorepo-config.json +49 -0
- package/examples/usage.md +289 -0
- package/package.json +58 -0
- package/scripts/debug-workflows.sh +339 -0
- package/scripts/parse-pipeline.js +29 -0
- package/scripts/test-job-order.cjs +140 -0
- package/scripts/validate-pipeline.cjs +379 -0
- package/scripts/verify-job-order.sh +30 -0
- package/src/cli/index.ts +414 -0
- package/src/generators/init.tpl.ts +126 -0
- package/src/generators/workflows.tpl.ts +80 -0
- package/src/templates/actions/calculate-version.yml.tpl.ts +124 -0
- package/src/templates/actions/create-pr.yml.tpl.ts +147 -0
- package/src/templates/actions/create-tag.yml.tpl.ts +112 -0
- package/src/templates/actions/detect-changes.yml.tpl.ts +87 -0
- package/src/templates/actions/manage-branch.yml.tpl.ts +132 -0
- package/src/templates/actions/promote-branch.yml.tpl.ts +364 -0
- package/src/templates/workflows/pipeline-path-based.yml.tpl.ts +706 -0
- package/src/types/index.ts +64 -0
- package/src/utils/README-ast-path-operations.md +390 -0
- package/src/utils/ast-path-operations.ts +581 -0
- package/src/utils/config.ts +64 -0
- package/src/utils/github-setup.ts +558 -0
- package/src/utils/idempotency.ts +215 -0
- package/src/utils/preflight.ts +306 -0
- package/src/utils/versioning.ts +244 -0
- package/tests/README.md +229 -0
- package/tests/TEST_STRUCTURE.md +256 -0
- package/tests/act/run-act-tests.sh +345 -0
- package/tests/debugging/debug-utils.ts +538 -0
- package/tests/debugging/debug-workflow.test.ts +339 -0
- package/tests/debugging/debug-workflows.sh +339 -0
- package/tests/debugging/iterative-debug.ts +652 -0
- package/tests/debugging/run-debug-tests.sh +431 -0
- package/tests/fixtures/basic-config.json +51 -0
- package/tests/fixtures/invalid-config.json +9 -0
- package/tests/fixtures/pipeline-generated.yml +235 -0
- package/tests/fixtures/pipeline-preserve-comments.yml +245 -0
- package/tests/fixtures/pipeline-user-modified.yml +245 -0
- package/tests/fixtures/test-config.json +58 -0
- package/tests/github-live/README.md +250 -0
- package/tests/github-local/JOB_WORKFLOW_TESTS.md +296 -0
- package/tests/github-local/README.md +240 -0
- package/tests/github-local/run-all-tests.sh +422 -0
- package/tests/github-local/test-job-workflows.sh +631 -0
- package/tests/github-local/test-pipeline-workflow.sh +440 -0
- package/tests/integration/generators.test.ts +578 -0
- package/tests/integration/path-based-template.test.ts +510 -0
- package/tests/integration/simple-path-based.test.ts +415 -0
- package/tests/setup.ts +56 -0
- package/tests/unit/ast-path-operations-extended.test.ts +302 -0
- package/tests/unit/cli.test.ts +541 -0
- package/tests/unit/config-extended.test.ts +412 -0
- package/tests/unit/config.test.ts +152 -0
- package/tests/unit/github-setup.test.ts +189 -0
- package/tests/unit/idempotency-isolated.test.ts +297 -0
- package/tests/unit/job-order.test.ts +157 -0
- package/tests/unit/pipeline-path-based.test.ts +511 -0
- package/tests/unit/validate-pipeline.test.ts +384 -0
- package/tests/unit/versioning-extended.test.ts +279 -0
- package/tests/unit/versioning.test.ts +241 -0
- package/tsconfig.debug.json +17 -0
- package/tsconfig.json +28 -0
- package/vitest.config.ts +51 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { parseDocument, stringify, YAMLMap, YAMLSeq, Scalar } from 'yaml';
|
|
2
|
+
/**
|
|
3
|
+
* Set a value at a specific path in the YAML AST
|
|
4
|
+
*
|
|
5
|
+
* Creates intermediate nodes as needed and sets the final value at the specified path.
|
|
6
|
+
* This is the core function for setting values in the YAML structure.
|
|
7
|
+
*
|
|
8
|
+
* @param {YAMLMap} doc - The YAML document to modify
|
|
9
|
+
* @param {string} path - Dot-notation path (e.g., 'jobs.changes.steps')
|
|
10
|
+
* @param {PathValue} value - Value to set at the path
|
|
11
|
+
*
|
|
12
|
+
* @throws {Error} When path navigation fails or parent is not a map
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* const doc = parseDocument('name: Pipeline')
|
|
17
|
+
* setPathValue(doc.contents, 'jobs.changes.runs-on', 'ubuntu-latest')
|
|
18
|
+
* // Results in: jobs: { changes: { 'runs-on': 'ubuntu-latest' } }
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export function setPathValue(doc, path, value, document, commentBefore, spaceBeforeComment) {
|
|
22
|
+
const pathParts = path.split('.');
|
|
23
|
+
let current = doc;
|
|
24
|
+
// Navigate to the parent of the target
|
|
25
|
+
for (let i = 0; i < pathParts.length - 1; i++) {
|
|
26
|
+
const part = pathParts[i];
|
|
27
|
+
if (current instanceof YAMLMap) {
|
|
28
|
+
let next = current.get(part);
|
|
29
|
+
if (!next) {
|
|
30
|
+
// Create missing intermediate nodes
|
|
31
|
+
next = new YAMLMap();
|
|
32
|
+
current.set(part, next);
|
|
33
|
+
}
|
|
34
|
+
current = next;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
throw new Error(`Cannot navigate to ${part} - parent is not a map`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Set the final value
|
|
41
|
+
const finalKey = pathParts[pathParts.length - 1];
|
|
42
|
+
if (current instanceof YAMLMap) {
|
|
43
|
+
let node;
|
|
44
|
+
// Check if value is already a node (from createValueFromString, etc.)
|
|
45
|
+
if (value && typeof value === 'object' && ('items' in value || 'type' in value)) {
|
|
46
|
+
// Value is already a node, use it directly
|
|
47
|
+
node = value;
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
// Value is not a node, create one
|
|
51
|
+
node = document && document.createNode ? document.createNode(value) : createNode(value);
|
|
52
|
+
}
|
|
53
|
+
// When commentBefore is provided, or when setting a job key (which may need comments added later),
|
|
54
|
+
// we need to create a Scalar key instead of a string key.
|
|
55
|
+
// This is because YAML's set() method creates a plain string key by default,
|
|
56
|
+
// but comments can only be attached to Scalar objects.
|
|
57
|
+
const isJobKey = pathParts.length === 2 && pathParts[0] === 'jobs';
|
|
58
|
+
if (commentBefore || isJobKey) {
|
|
59
|
+
// Create a Scalar key (with or without comment)
|
|
60
|
+
const scalarKey = new Scalar(finalKey);
|
|
61
|
+
if (commentBefore) {
|
|
62
|
+
;
|
|
63
|
+
scalarKey.commentBefore = commentBefore;
|
|
64
|
+
}
|
|
65
|
+
// Add blank line before the comment if requested
|
|
66
|
+
if (spaceBeforeComment) {
|
|
67
|
+
;
|
|
68
|
+
scalarKey.spaceBefore = true;
|
|
69
|
+
}
|
|
70
|
+
// Add the pair to the map with a Scalar key
|
|
71
|
+
current.add({ key: scalarKey, value: node });
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
// Normal case: use the simple set() method which creates a string key
|
|
75
|
+
current.set(finalKey, node);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
else {
|
|
79
|
+
throw new Error(`Cannot set ${finalKey} - parent is not a map`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get a value at a specific path in the YAML AST
|
|
84
|
+
*
|
|
85
|
+
* Navigates to the specified path and returns the node if found, null otherwise.
|
|
86
|
+
* This is useful for checking if a path exists before applying operations.
|
|
87
|
+
*
|
|
88
|
+
* @param {YAMLMap} doc - The YAML document to read from
|
|
89
|
+
* @param {string} path - Dot-notation path (e.g., 'jobs.changes.steps')
|
|
90
|
+
* @returns {Node | null} The node at the path, or null if not found
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const doc = parseDocument('jobs: { changes: { runs-on: ubuntu-latest } }')
|
|
95
|
+
* const value = getPathValue(doc.contents, 'jobs.changes.runs-on')
|
|
96
|
+
* console.log(value) // Scalar('ubuntu-latest')
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export function getPathValue(doc, path) {
|
|
100
|
+
const pathParts = path.split('.');
|
|
101
|
+
let current = doc;
|
|
102
|
+
for (const part of pathParts) {
|
|
103
|
+
if (current instanceof YAMLMap) {
|
|
104
|
+
current = current.get(part);
|
|
105
|
+
if (!current)
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
return null;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return current;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Ensure a path exists and apply the specified operation
|
|
116
|
+
*
|
|
117
|
+
* This is the main orchestration function that handles all path operations.
|
|
118
|
+
* It checks if the path exists, applies the appropriate operation based on
|
|
119
|
+
* the configuration, and handles required vs optional paths.
|
|
120
|
+
*
|
|
121
|
+
* @param {YAMLMap} doc - The YAML document to modify
|
|
122
|
+
* @param {PathOperationConfig} config - Operation configuration
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* const config: PathOperationConfig = {
|
|
127
|
+
* path: 'jobs.changes.runs-on',
|
|
128
|
+
* operation: 'set',
|
|
129
|
+
* value: 'ubuntu-latest',
|
|
130
|
+
* required: true
|
|
131
|
+
* }
|
|
132
|
+
*
|
|
133
|
+
* ensurePathAndApply(doc, config)
|
|
134
|
+
* ```
|
|
135
|
+
*/
|
|
136
|
+
export function ensurePathAndApply(doc, config, document) {
|
|
137
|
+
const { path, operation, value, required = true, commentBefore, spaceBeforeComment } = config;
|
|
138
|
+
// Check if path exists
|
|
139
|
+
const existingValue = getPathValue(doc, path);
|
|
140
|
+
if (!existingValue && !required) {
|
|
141
|
+
// Path doesn't exist and not required - skip
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
// Apply operation based on whether path exists or not
|
|
145
|
+
// For required paths that don't exist, we still respect the operation type
|
|
146
|
+
switch (operation) {
|
|
147
|
+
case 'set':
|
|
148
|
+
setPathValue(doc, path, value, document, commentBefore, spaceBeforeComment);
|
|
149
|
+
break;
|
|
150
|
+
case 'merge':
|
|
151
|
+
// Merge will handle non-existent paths by creating them
|
|
152
|
+
mergePathValue(doc, path, value, document);
|
|
153
|
+
break;
|
|
154
|
+
case 'overwrite':
|
|
155
|
+
setPathValue(doc, path, value, document, commentBefore, spaceBeforeComment);
|
|
156
|
+
break;
|
|
157
|
+
case 'preserve':
|
|
158
|
+
// Only preserve if path exists, otherwise create it
|
|
159
|
+
if (!existingValue) {
|
|
160
|
+
setPathValue(doc, path, value, document, commentBefore, spaceBeforeComment);
|
|
161
|
+
}
|
|
162
|
+
// If exists, do nothing - keep existing value
|
|
163
|
+
break;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Merge a value at a specific path (for objects/arrays)
|
|
168
|
+
*
|
|
169
|
+
* Intelligently merges values based on their type:
|
|
170
|
+
* - Objects: Merges key-value pairs, preserving existing keys
|
|
171
|
+
* - Arrays: Adds new items that don't already exist
|
|
172
|
+
* - Other types: Falls back to overwrite behavior
|
|
173
|
+
*
|
|
174
|
+
* @param {YAMLMap} doc - The YAML document to modify
|
|
175
|
+
* @param {string} path - Dot-notation path to merge at
|
|
176
|
+
* @param {PathValue} value - Value to merge
|
|
177
|
+
*
|
|
178
|
+
* @example
|
|
179
|
+
* ```typescript
|
|
180
|
+
* // Merge object properties
|
|
181
|
+
* mergePathValue(doc, 'on.workflow_call.inputs', {
|
|
182
|
+
* version: { description: 'Version to deploy' },
|
|
183
|
+
* environment: { description: 'Environment to deploy to' }
|
|
184
|
+
* })
|
|
185
|
+
*
|
|
186
|
+
* // Merge array items
|
|
187
|
+
* mergePathValue(doc, 'on.pull_request.branches', ['feature-branch'])
|
|
188
|
+
* ```
|
|
189
|
+
*/
|
|
190
|
+
function mergePathValue(doc, path, value, document) {
|
|
191
|
+
const existingValue = getPathValue(doc, path);
|
|
192
|
+
if (!existingValue) {
|
|
193
|
+
setPathValue(doc, path, value, document);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
// Merge logic based on type
|
|
197
|
+
if (existingValue instanceof YAMLMap && typeof value === 'object') {
|
|
198
|
+
// Merge objects
|
|
199
|
+
const newMap = (document && document.createNode ? document.createNode(value) : createNode(value));
|
|
200
|
+
for (const pair of newMap.items) {
|
|
201
|
+
const key = pair.key;
|
|
202
|
+
const val = pair.value;
|
|
203
|
+
existingValue.set(key, val);
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
else if (existingValue instanceof YAMLSeq && Array.isArray(value)) {
|
|
207
|
+
// Merge arrays - add new items that don't exist
|
|
208
|
+
const newSeq = (document && document.createNode ? document.createNode(value) : createNode(value));
|
|
209
|
+
for (const item of newSeq.items) {
|
|
210
|
+
if (!existingValue.items.some(existing => stringify(existing) === stringify(item))) {
|
|
211
|
+
existingValue.items.push(item);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// Fallback to overwrite
|
|
217
|
+
setPathValue(doc, path, value, document);
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Create a YAML node from a JavaScript value, YAML node, or parsed document
|
|
222
|
+
*
|
|
223
|
+
* This is the core value conversion function that handles all supported value types.
|
|
224
|
+
* It intelligently converts JavaScript values to appropriate YAML nodes.
|
|
225
|
+
*
|
|
226
|
+
* @param {PathValue} value - Value to convert to YAML node
|
|
227
|
+
* @returns {Node} The converted YAML node
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* // Convert object
|
|
232
|
+
* const node = createNode({ key: 'value' })
|
|
233
|
+
*
|
|
234
|
+
* // Convert array
|
|
235
|
+
* const node = createNode(['item1', 'item2'])
|
|
236
|
+
*
|
|
237
|
+
* // Convert string
|
|
238
|
+
* const node = createNode('simple string')
|
|
239
|
+
*
|
|
240
|
+
* // Convert YAML string
|
|
241
|
+
* const node = createNode(createValueFromString(`
|
|
242
|
+
* runs-on: ubuntu-latest
|
|
243
|
+
* steps:
|
|
244
|
+
* - name: Example step
|
|
245
|
+
* run: echo "Hello"
|
|
246
|
+
* `))
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
function createNode(value) {
|
|
250
|
+
// If it's already a YAML node, return it
|
|
251
|
+
if (value && typeof value === 'object' && 'type' in value) {
|
|
252
|
+
return value;
|
|
253
|
+
}
|
|
254
|
+
// If it's a parsed document, extract the contents
|
|
255
|
+
if (value && typeof value === 'object' && 'contents' in value) {
|
|
256
|
+
const contents = value.contents;
|
|
257
|
+
// If contents is a single item, return it directly
|
|
258
|
+
if (contents && typeof contents === 'object' && 'type' in contents) {
|
|
259
|
+
return contents;
|
|
260
|
+
}
|
|
261
|
+
return contents;
|
|
262
|
+
}
|
|
263
|
+
// Handle primitive types
|
|
264
|
+
if (typeof value === 'string') {
|
|
265
|
+
return new Scalar(value);
|
|
266
|
+
}
|
|
267
|
+
else if (typeof value === 'number') {
|
|
268
|
+
return new Scalar(value);
|
|
269
|
+
}
|
|
270
|
+
else if (typeof value === 'boolean') {
|
|
271
|
+
return new Scalar(value);
|
|
272
|
+
}
|
|
273
|
+
else if (Array.isArray(value)) {
|
|
274
|
+
const seq = new YAMLSeq();
|
|
275
|
+
for (const item of value) {
|
|
276
|
+
seq.items.push(createNode(item));
|
|
277
|
+
}
|
|
278
|
+
return seq;
|
|
279
|
+
}
|
|
280
|
+
else if (typeof value === 'object' && value !== null) {
|
|
281
|
+
const map = new YAMLMap();
|
|
282
|
+
for (const [key, val] of Object.entries(value)) {
|
|
283
|
+
map.set(key, createNode(val));
|
|
284
|
+
}
|
|
285
|
+
return map;
|
|
286
|
+
}
|
|
287
|
+
else {
|
|
288
|
+
return new Scalar(value);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Apply multiple path operations to a document
|
|
293
|
+
*
|
|
294
|
+
* This is the main entry point for applying multiple operations to a YAML document.
|
|
295
|
+
* It processes all operations in order and applies them to the document.
|
|
296
|
+
*
|
|
297
|
+
* @param {YAMLMap} doc - The YAML document to modify
|
|
298
|
+
* @param {PathOperationConfig[]} operations - Array of operations to apply
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```typescript
|
|
302
|
+
* const operations: PathOperationConfig[] = [
|
|
303
|
+
* {
|
|
304
|
+
* path: 'on.workflow_call.inputs.version',
|
|
305
|
+
* operation: 'set',
|
|
306
|
+
* value: { description: 'Version to deploy', required: false, type: 'string' }
|
|
307
|
+
* },
|
|
308
|
+
* {
|
|
309
|
+
* path: 'jobs.changes',
|
|
310
|
+
* operation: 'overwrite',
|
|
311
|
+
* value: createValueFromString(`
|
|
312
|
+
* runs-on: ubuntu-latest
|
|
313
|
+
* steps:
|
|
314
|
+
* - uses: ./.github/actions/detect-changes
|
|
315
|
+
* `)
|
|
316
|
+
* }
|
|
317
|
+
* ]
|
|
318
|
+
*
|
|
319
|
+
* applyPathOperations(doc, operations)
|
|
320
|
+
* ```
|
|
321
|
+
*/
|
|
322
|
+
export function applyPathOperations(doc, operations, document) {
|
|
323
|
+
for (const operation of operations) {
|
|
324
|
+
ensurePathAndApply(doc, operation, document);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
/**
|
|
328
|
+
* Helper functions for creating values
|
|
329
|
+
*
|
|
330
|
+
* These convenience functions make it easier to create YAML nodes from different
|
|
331
|
+
* value types. They handle the parsing and conversion automatically.
|
|
332
|
+
*/
|
|
333
|
+
/**
|
|
334
|
+
* Create a YAML node from a YAML string
|
|
335
|
+
*
|
|
336
|
+
* Parses a YAML string and returns the root node. This is useful for complex
|
|
337
|
+
* multi-line YAML structures like job definitions.
|
|
338
|
+
*
|
|
339
|
+
* @param {string} yamlString - YAML string to parse
|
|
340
|
+
* @returns {Node} The parsed YAML node
|
|
341
|
+
*
|
|
342
|
+
* @example
|
|
343
|
+
* ```typescript
|
|
344
|
+
* const node = createValueFromString(`
|
|
345
|
+
* runs-on: ubuntu-latest
|
|
346
|
+
* steps:
|
|
347
|
+
* - name: Checkout code
|
|
348
|
+
* uses: actions/checkout@v3
|
|
349
|
+
* - name: Run tests
|
|
350
|
+
* run: npm test
|
|
351
|
+
* `)
|
|
352
|
+
* ```
|
|
353
|
+
*/
|
|
354
|
+
export function createValueFromString(yamlString, context, document) {
|
|
355
|
+
// Evaluate JavaScript template literals in the string using the provided context
|
|
356
|
+
// Use a more sophisticated approach that handles nested braces
|
|
357
|
+
let processedString = yamlString;
|
|
358
|
+
let match;
|
|
359
|
+
const regex = /\$\{([^{}]+)\}/g;
|
|
360
|
+
while ((match = regex.exec(processedString)) !== null) {
|
|
361
|
+
const [fullMatch, expression] = match;
|
|
362
|
+
try {
|
|
363
|
+
// Create a function that evaluates the expression with the context
|
|
364
|
+
const func = new Function('ctx', `return ${expression}`);
|
|
365
|
+
const result = func(context || {});
|
|
366
|
+
processedString = processedString.replace(fullMatch, JSON.stringify(result));
|
|
367
|
+
// Reset regex lastIndex to avoid issues with string replacement
|
|
368
|
+
regex.lastIndex = 0;
|
|
369
|
+
}
|
|
370
|
+
catch (error) {
|
|
371
|
+
// If evaluation fails, return the original expression as a string
|
|
372
|
+
processedString = processedString.replace(fullMatch, `"${expression}"`);
|
|
373
|
+
regex.lastIndex = 0;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Parse the YAML string and return the root content as a proper Node
|
|
377
|
+
const doc = parseDocument(processedString);
|
|
378
|
+
return doc.contents;
|
|
379
|
+
}
|
|
380
|
+
/**
|
|
381
|
+
* Create a YAML node from a JavaScript object
|
|
382
|
+
*
|
|
383
|
+
* Converts a plain JavaScript object to a YAML map node.
|
|
384
|
+
*
|
|
385
|
+
* @param {object} obj - JavaScript object to convert
|
|
386
|
+
* @returns {Node} The converted YAML map node
|
|
387
|
+
*
|
|
388
|
+
* @example
|
|
389
|
+
* ```typescript
|
|
390
|
+
* const node = createValueFromObject({
|
|
391
|
+
* description: 'The version to deploy',
|
|
392
|
+
* required: false,
|
|
393
|
+
* type: 'string'
|
|
394
|
+
* })
|
|
395
|
+
* ```
|
|
396
|
+
*/
|
|
397
|
+
export function createValueFromObject(obj, doc) {
|
|
398
|
+
if (doc && doc.createNode) {
|
|
399
|
+
return doc.createNode(obj);
|
|
400
|
+
}
|
|
401
|
+
return createNode(obj);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Create a YAML node from a JavaScript array
|
|
405
|
+
*
|
|
406
|
+
* Converts a JavaScript array to a YAML sequence node.
|
|
407
|
+
*
|
|
408
|
+
* @param {any[]} arr - JavaScript array to convert
|
|
409
|
+
* @returns {Node} The converted YAML sequence node
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* ```typescript
|
|
413
|
+
* const node = createValueFromArray(['develop', 'staging', 'main'])
|
|
414
|
+
* ```
|
|
415
|
+
*/
|
|
416
|
+
export function createValueFromArray(arr) {
|
|
417
|
+
return createNode(arr);
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=ast-path-operations.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-path-operations.js","sourceRoot":"","sources":["../../src/utils/ast-path-operations.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,UAAU,GAAI,aAAa,MAAM,QAS7C,CAAA;AAED,eAAO,MAAM,cAAc,GAAI,QAAQ,GAAG,YAiDzC,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { cosmiconfigSync } from 'cosmiconfig';
|
|
2
|
+
export const loadConfig = (configPath) => {
|
|
3
|
+
const explorer = cosmiconfigSync('pipecraft');
|
|
4
|
+
const result = configPath ? explorer.load(configPath) : explorer.search();
|
|
5
|
+
if (!result) {
|
|
6
|
+
throw new Error(`No configuration file found. Expected: ${configPath || '.pipecraftrc.json'}`);
|
|
7
|
+
}
|
|
8
|
+
return result.config;
|
|
9
|
+
};
|
|
10
|
+
export const validateConfig = (config) => {
|
|
11
|
+
const requiredFields = ['ciProvider', 'mergeStrategy', 'requireConventionalCommits', 'initialBranch', 'finalBranch', 'branchFlow', 'domains'];
|
|
12
|
+
for (const field of requiredFields) {
|
|
13
|
+
if (!(field in config)) {
|
|
14
|
+
throw new Error(`Missing required field: ${field}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (!['github', 'gitlab'].includes(config.ciProvider)) {
|
|
18
|
+
throw new Error('ciProvider must be either "github" or "gitlab"');
|
|
19
|
+
}
|
|
20
|
+
if (!['fast-forward', 'merge'].includes(config.mergeStrategy)) {
|
|
21
|
+
throw new Error('mergeStrategy must be either "fast-forward" or "merge"');
|
|
22
|
+
}
|
|
23
|
+
if (!Array.isArray(config.branchFlow) || config.branchFlow.length < 2) {
|
|
24
|
+
throw new Error('branchFlow must be an array with at least 2 branches');
|
|
25
|
+
}
|
|
26
|
+
if (typeof config.domains !== 'object') {
|
|
27
|
+
throw new Error('domains must be an object');
|
|
28
|
+
}
|
|
29
|
+
for (const [domainName, domainConfig] of Object.entries(config.domains)) {
|
|
30
|
+
if (!domainConfig || typeof domainConfig !== 'object') {
|
|
31
|
+
throw new Error(`Domain "${domainName}" must be an object`);
|
|
32
|
+
}
|
|
33
|
+
if (!domainConfig.paths || !Array.isArray(domainConfig.paths)) {
|
|
34
|
+
throw new Error(`Domain "${domainName}" must have a "paths" array`);
|
|
35
|
+
}
|
|
36
|
+
if (domainConfig.paths.length === 0) {
|
|
37
|
+
throw new Error(`Domain "${domainName}" must have at least one path pattern`);
|
|
38
|
+
}
|
|
39
|
+
// Set defaults for optional properties
|
|
40
|
+
if (domainConfig.testable === undefined) {
|
|
41
|
+
domainConfig.testable = true;
|
|
42
|
+
}
|
|
43
|
+
if (domainConfig.deployable === undefined) {
|
|
44
|
+
domainConfig.deployable = true;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
};
|
|
49
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAG7C,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,UAAmB,EAAE,EAAE;IAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAA;IAEzE,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,0CAA0C,UAAU,IAAI,mBAAmB,EAAE,CAAC,CAAA;IAChG,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAA;AACtB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,MAAW,EAAE,EAAE;IAC5C,MAAM,cAAc,GAAG,CAAC,YAAY,EAAE,eAAe,EAAE,4BAA4B,EAAE,eAAe,EAAE,aAAa,EAAE,YAAY,EAAE,SAAS,CAAC,CAAA;IAE7I,KAAK,MAAM,KAAK,IAAI,cAAc,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAA;QACrD,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAA;IACnE,CAAC;IAED,IAAI,CAAC,CAAC,cAAc,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QAC9D,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAA;IAC3E,CAAC;IAED,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAA;IACzE,CAAC;IAED,IAAI,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAA;IAC9C,CAAC;IAED,KAAK,MAAM,CAAC,UAAU,EAAE,YAAY,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAA6B,EAAE,CAAC;QACpG,IAAI,CAAC,YAAY,IAAI,OAAO,YAAY,KAAK,QAAQ,EAAE,CAAC;YACtD,MAAM,IAAI,KAAK,CAAC,WAAW,UAAU,qBAAqB,CAAC,CAAA;QAC7D,CAAC;QAED,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,KAAK,CAAC,WAAW,UAAU,6BAA6B,CAAC,CAAA;QACrE,CAAC;QAED,IAAI,YAAY,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,WAAW,UAAU,uCAAuC,CAAC,CAAA;QAC/E,CAAC;QAED,uCAAuC;QACvC,IAAI,YAAY,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YACxC,YAAY,CAAC,QAAQ,GAAG,IAAI,CAAA;QAC9B,CAAC;QACD,IAAI,YAAY,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YAC1C,YAAY,CAAC,UAAU,GAAG,IAAI,CAAA;QAChC,CAAC;IACH,CAAC;IAGD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
interface WorkflowPermissions {
|
|
2
|
+
default_workflow_permissions: 'read' | 'write';
|
|
3
|
+
can_approve_pull_request_reviews: boolean;
|
|
4
|
+
}
|
|
5
|
+
interface RepositoryInfo {
|
|
6
|
+
owner: string;
|
|
7
|
+
repo: string;
|
|
8
|
+
remote: string;
|
|
9
|
+
}
|
|
10
|
+
interface BranchProtectionRules {
|
|
11
|
+
required_status_checks: null | {
|
|
12
|
+
strict: boolean;
|
|
13
|
+
contexts: string[];
|
|
14
|
+
};
|
|
15
|
+
enforce_admins: boolean;
|
|
16
|
+
required_pull_request_reviews: null | {
|
|
17
|
+
dismiss_stale_reviews: boolean;
|
|
18
|
+
require_code_owner_reviews: boolean;
|
|
19
|
+
required_approving_review_count: number;
|
|
20
|
+
};
|
|
21
|
+
restrictions: null;
|
|
22
|
+
allow_force_pushes: boolean;
|
|
23
|
+
allow_deletions: boolean;
|
|
24
|
+
required_linear_history: boolean;
|
|
25
|
+
required_conversation_resolution: boolean;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Get repository information from git remote
|
|
29
|
+
*/
|
|
30
|
+
export declare function getRepositoryInfo(): RepositoryInfo;
|
|
31
|
+
/**
|
|
32
|
+
* Get GitHub token from environment or gh CLI
|
|
33
|
+
*/
|
|
34
|
+
export declare function getGitHubToken(): string;
|
|
35
|
+
/**
|
|
36
|
+
* Get current workflow permissions
|
|
37
|
+
*/
|
|
38
|
+
export declare function getWorkflowPermissions(owner: string, repo: string, token: string): Promise<WorkflowPermissions>;
|
|
39
|
+
/**
|
|
40
|
+
* Update workflow permissions
|
|
41
|
+
*/
|
|
42
|
+
export declare function updateWorkflowPermissions(owner: string, repo: string, token: string, permissions: Partial<WorkflowPermissions>): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Determine required permission changes without prompting
|
|
45
|
+
* Returns: changes object if changes needed, null if already correct
|
|
46
|
+
*/
|
|
47
|
+
export declare function getRequiredPermissionChanges(currentPermissions: WorkflowPermissions): Partial<WorkflowPermissions> | null;
|
|
48
|
+
/**
|
|
49
|
+
* Display current permissions and prompt for changes
|
|
50
|
+
* Returns: changes object if user accepted changes, 'declined' if user declined, null if already correct
|
|
51
|
+
*/
|
|
52
|
+
export declare function promptPermissionChanges(currentPermissions: WorkflowPermissions): Promise<Partial<WorkflowPermissions> | null | 'declined'>;
|
|
53
|
+
/**
|
|
54
|
+
* Get branch protection rules
|
|
55
|
+
*/
|
|
56
|
+
export declare function getBranchProtection(owner: string, repo: string, branch: string, token: string): Promise<BranchProtectionRules | null>;
|
|
57
|
+
/**
|
|
58
|
+
* Update branch protection rules to enable auto-merge
|
|
59
|
+
*/
|
|
60
|
+
export declare function updateBranchProtection(owner: string, repo: string, branch: string, token: string): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* Enable auto-merge feature for the repository
|
|
63
|
+
*/
|
|
64
|
+
export declare function enableAutoMerge(owner: string, repo: string, token: string): Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Configure branch protection for branches that need auto-merge
|
|
67
|
+
*/
|
|
68
|
+
export declare function configureBranchProtection(repoInfo: RepositoryInfo, token: string, autoApply: boolean): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* Main setup function
|
|
71
|
+
*/
|
|
72
|
+
export declare function setupGitHubPermissions(autoApply?: boolean): Promise<void>;
|
|
73
|
+
export {};
|
|
74
|
+
//# sourceMappingURL=github-setup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-setup.d.ts","sourceRoot":"","sources":["../../src/utils/github-setup.ts"],"names":[],"mappings":"AAKA,UAAU,mBAAmB;IAC3B,4BAA4B,EAAE,MAAM,GAAG,OAAO,CAAA;IAC9C,gCAAgC,EAAE,OAAO,CAAA;CAC1C;AAED,UAAU,cAAc;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;CACf;AAED,UAAU,qBAAqB;IAC7B,sBAAsB,EAAE,IAAI,GAAG;QAC7B,MAAM,EAAE,OAAO,CAAA;QACf,QAAQ,EAAE,MAAM,EAAE,CAAA;KACnB,CAAA;IACD,cAAc,EAAE,OAAO,CAAA;IACvB,6BAA6B,EAAE,IAAI,GAAG;QACpC,qBAAqB,EAAE,OAAO,CAAA;QAC9B,0BAA0B,EAAE,OAAO,CAAA;QACnC,+BAA+B,EAAE,MAAM,CAAA;KACxC,CAAA;IACD,YAAY,EAAE,IAAI,CAAA;IAClB,kBAAkB,EAAE,OAAO,CAAA;IAC3B,eAAe,EAAE,OAAO,CAAA;IACxB,uBAAuB,EAAE,OAAO,CAAA;IAChC,gCAAgC,EAAE,OAAO,CAAA;CAC1C;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,cAAc,CAqBlD;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAuBvC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,mBAAmB,CAAC,CAkB9B;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,OAAO,CAAC,mBAAmB,CAAC,GACxC,OAAO,CAAC,IAAI,CAAC,CAmBf;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,kBAAkB,EAAE,mBAAmB,GACtC,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAoBrC;AAED;;;GAGG;AACH,wBAAsB,uBAAuB,CAC3C,kBAAkB,EAAE,mBAAmB,GACtC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,GAAG,IAAI,GAAG,UAAU,CAAC,CA6D3D;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAuBvC;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,IAAI,CAAC,CAmCf;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CA2ClB;AAED;;GAEG;AACH,wBAAsB,yBAAyB,CAC7C,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,OAAO,GACjB,OAAO,CAAC,IAAI,CAAC,CA2Ff;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,SAAS,GAAE,OAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAmFtF"}
|