@chenguangyao/devflow-kit 0.1.43
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 +232 -0
- package/LICENSE +21 -0
- package/README.md +539 -0
- package/bin/devflow.js +9 -0
- package/docs/RFC-001-devflow-kit.md +617 -0
- package/docs/RFC-002-workflow-kernel.md +134 -0
- package/docs/enterprise-integration-supplement.md +274 -0
- package/docs/internal-gitlab-setup.md +426 -0
- package/docs/marketplace-skills.md +231 -0
- package/docs/migration-from-arb.md +232 -0
- package/docs/tooling-overview.md +774 -0
- package/docs/workflow-orchestration.md +695 -0
- package/docs/workflow-ui-prototype.html +271 -0
- package/package.json +52 -0
- package/schemas/config.schema.json +51 -0
- package/schemas/delta.schema.json +22 -0
- package/schemas/state.schema.json +130 -0
- package/schemas/status-surface.schema.json +197 -0
- package/schemas/workflow-confirmation-surface.schema.json +70 -0
- package/schemas/workflow-picker.schema.json +94 -0
- package/scripts/postinstall.js +101 -0
- package/scripts/render-workflow-ui-prototype.js +271 -0
- package/skills/apply/SKILL.md +313 -0
- package/skills/apply/references/discipline-checklist.md +145 -0
- package/skills/apply/references/subagent-implementer-prompt.md +113 -0
- package/skills/apply/references/subagent-orchestration.md +150 -0
- package/skills/apply/references/subagent-reviewer-prompt.md +180 -0
- package/skills/apply/references/tdd-loop.md +287 -0
- package/skills/apply/references/when-plan-is-wrong.md +279 -0
- package/skills/apply/references/worktree-swarm.md +292 -0
- package/skills/archive/SKILL.md +229 -0
- package/skills/archive/references/conflict-resolution.md +336 -0
- package/skills/archive/references/knowledge-deposit.md +381 -0
- package/skills/archive/references/spec-merge.md +365 -0
- package/skills/brainstorm/SKILL.md +123 -0
- package/skills/brainstorm/references/proposal-template.md +244 -0
- package/skills/brainstorm/references/question-catalog.md +168 -0
- package/skills/brainstorm/references/session-template.md +184 -0
- package/skills/ci-fix/SKILL.md +63 -0
- package/skills/ci-fix/references/loop.md +25 -0
- package/skills/code-review/SKILL.md +279 -0
- package/skills/code-review/references/escalation-playbook.md +192 -0
- package/skills/code-review/references/language-cheatsheets/go.md +175 -0
- package/skills/code-review/references/language-cheatsheets/java-spring-mybatis.md +246 -0
- package/skills/code-review/references/language-cheatsheets/python.md +170 -0
- package/skills/code-review/references/language-cheatsheets/vue.md +199 -0
- package/skills/code-review/references/output-template.md +275 -0
- package/skills/code-review/references/review-checklist.md +251 -0
- package/skills/complexity-grading/SKILL.md +259 -0
- package/skills/deliver/SKILL.md +271 -0
- package/skills/deliver/references/delivery-modes.md +299 -0
- package/skills/deliver/references/notify.md +359 -0
- package/skills/deliver/references/pr-description.md +319 -0
- package/skills/dependency-upgrade/SKILL.md +57 -0
- package/skills/dependency-upgrade/references/risk-matrix.md +38 -0
- package/skills/df-orchestrator/SKILL.md +407 -0
- package/skills/df-orchestrator/references/complexity-grading.md +177 -0
- package/skills/df-orchestrator/references/escalation-matrix.md +191 -0
- package/skills/df-orchestrator/references/routing-rules.md +290 -0
- package/skills/df-orchestrator/references/workflow-state-machine.md +208 -0
- package/skills/frontend-quality/SKILL.md +61 -0
- package/skills/frontend-quality/references/checklist.md +35 -0
- package/skills/handoff-resume/SKILL.md +59 -0
- package/skills/handoff-resume/references/handoff-template.md +54 -0
- package/skills/plan/SKILL.md +166 -0
- package/skills/plan/references/task-breakdown.md +207 -0
- package/skills/plan/references/task-sequencing.md +143 -0
- package/skills/plan/references/task-template.md +248 -0
- package/skills/requirement-analysis/SKILL.md +499 -0
- package/skills/requirement-analysis/references/acceptance-criteria.md +183 -0
- package/skills/requirement-analysis/references/code-recon.md +151 -0
- package/skills/requirement-analysis/references/edge-case-catalog.md +164 -0
- package/skills/requirement-analysis/references/requirement-template.md +339 -0
- package/skills/requirement-analysis/references/scope-negotiation.md +162 -0
- package/skills/security-hardening/SKILL.md +60 -0
- package/skills/security-hardening/references/checklist.md +42 -0
- package/skills/tech-spec/SKILL.md +388 -0
- package/skills/tech-spec/references/api-contract-design.md +172 -0
- package/skills/tech-spec/references/decision-records.md +110 -0
- package/skills/tech-spec/references/design-template.md +301 -0
- package/skills/tech-spec/references/rollout-and-rollback.md +203 -0
- package/skills/tech-spec/references/spec-delta-conventions.md +250 -0
- package/skills/tech-spec/references/transaction-patterns.md +212 -0
- package/skills/test-spec/SKILL.md +219 -0
- package/skills/test-spec/references/coverage-strategy.md +218 -0
- package/skills/test-spec/references/edge-case-to-test.md +143 -0
- package/skills/test-spec/references/test-case-template.md +276 -0
- package/skills/verify/SKILL.md +232 -0
- package/skills/verify/references/nfr-verification.md +292 -0
- package/skills/verify/references/report-templates.md +510 -0
- package/skills/verify/references/self-test-guide.md +240 -0
- package/skills/verify/references/verify-rollback-map.md +247 -0
- package/src/cli/commands/_helpers.js +108 -0
- package/src/cli/commands/_submit.js +718 -0
- package/src/cli/commands/apply.js +198 -0
- package/src/cli/commands/archive.js +180 -0
- package/src/cli/commands/checkpoint.js +113 -0
- package/src/cli/commands/deliver.js +377 -0
- package/src/cli/commands/deploy.js +504 -0
- package/src/cli/commands/design.js +158 -0
- package/src/cli/commands/disable.js +21 -0
- package/src/cli/commands/doctor.js +178 -0
- package/src/cli/commands/enable.js +21 -0
- package/src/cli/commands/flow.js +645 -0
- package/src/cli/commands/help.js +93 -0
- package/src/cli/commands/ingest.js +602 -0
- package/src/cli/commands/init.js +341 -0
- package/src/cli/commands/knowledge.js +523 -0
- package/src/cli/commands/logs.js +43 -0
- package/src/cli/commands/new.js +202 -0
- package/src/cli/commands/plan.js +49 -0
- package/src/cli/commands/propose.js +27 -0
- package/src/cli/commands/provider.js +698 -0
- package/src/cli/commands/report.js +143 -0
- package/src/cli/commands/requirement.js +227 -0
- package/src/cli/commands/review.js +301 -0
- package/src/cli/commands/skills.js +457 -0
- package/src/cli/commands/status.js +925 -0
- package/src/cli/commands/switch.js +27 -0
- package/src/cli/commands/sync.js +47 -0
- package/src/cli/commands/test.js +366 -0
- package/src/cli/commands/uninstall.js +32 -0
- package/src/cli/commands/update.js +74 -0
- package/src/cli/commands/verify.js +354 -0
- package/src/cli/commands/worktree.js +78 -0
- package/src/cli/index.js +72 -0
- package/src/cli/parse-args.js +102 -0
- package/src/core/autodetect.js +271 -0
- package/src/core/change.js +208 -0
- package/src/core/checkpoint.js +217 -0
- package/src/core/config.js +60 -0
- package/src/core/delta.js +290 -0
- package/src/core/markers.js +59 -0
- package/src/core/paths.js +173 -0
- package/src/core/plan-tasks.js +36 -0
- package/src/core/project-routing.js +285 -0
- package/src/core/projects.js +200 -0
- package/src/core/state.js +200 -0
- package/src/core/workflow-check.js +177 -0
- package/src/core/workflow-init.js +34 -0
- package/src/core/workflow-picker.js +154 -0
- package/src/core/workflow-policy.js +119 -0
- package/src/core/workflow-suggest.js +181 -0
- package/src/core/workflow-verify.js +88 -0
- package/src/core/workflow.js +433 -0
- package/src/core/worktree.js +241 -0
- package/src/knowledge/categories.js +107 -0
- package/src/knowledge/classify.js +125 -0
- package/src/knowledge/deposit.js +414 -0
- package/src/knowledge/migrate.js +149 -0
- package/src/knowledge/mr.js +219 -0
- package/src/knowledge/query.js +131 -0
- package/src/knowledge/registry.js +151 -0
- package/src/knowledge/sync.js +179 -0
- package/src/providers/base.js +74 -0
- package/src/providers/drivers/api-yapi.js +78 -0
- package/src/providers/drivers/ci-jenkins.js +109 -0
- package/src/providers/drivers/intake-confluence.js +544 -0
- package/src/providers/drivers/kb-git.js +549 -0
- package/src/providers/drivers/kb-weknora.js +472 -0
- package/src/providers/drivers/notify-smtp.js +515 -0
- package/src/providers/drivers/observability-oss.js +43 -0
- package/src/providers/drivers/observability-sls.js +50 -0
- package/src/providers/lifecycle.js +135 -0
- package/src/providers/loader.js +132 -0
- package/src/providers/local.js +190 -0
- package/src/providers/userconfig.js +283 -0
- package/src/reports/aggregate.js +185 -0
- package/src/reports/coverage.js +163 -0
- package/src/reports/detect.js +143 -0
- package/src/reports/parse.js +236 -0
- package/src/templates/files/ci/github.yml +38 -0
- package/src/templates/files/ci/gitlab.yml +27 -0
- package/src/templates/files/design.md +63 -0
- package/src/templates/files/ide/devflow-workflow.md +58 -0
- package/src/templates/files/ide/project-overview-reference.md +1 -0
- package/src/templates/files/ide/project-overview.md +27 -0
- package/src/templates/files/knowledge-index.json +17 -0
- package/src/templates/files/knowledge.md +28 -0
- package/src/templates/files/meta.json +8 -0
- package/src/templates/files/plan.md +38 -0
- package/src/templates/files/proposal.md +33 -0
- package/src/templates/files/reports/contract-test.md +40 -0
- package/src/templates/files/reports/e2e-test.md +30 -0
- package/src/templates/files/reports/integration-test.md +36 -0
- package/src/templates/files/reports/joint-test.md +58 -0
- package/src/templates/files/reports/perf.md +24 -0
- package/src/templates/files/reports/regression.md +20 -0
- package/src/templates/files/reports/remote-test.md +55 -0
- package/src/templates/files/reports/self-test.md +43 -0
- package/src/templates/files/reports/smoke-test.md +22 -0
- package/src/templates/files/reports/unit-test.md +36 -0
- package/src/templates/files/requirement.md +51 -0
- package/src/templates/files/review.md +38 -0
- package/src/templates/files/tests.md +36 -0
- package/src/templates/files/verify.md +32 -0
- package/src/templates/index.js +21 -0
- package/src/utils/log.js +37 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* Provider base classes & types (JS, doc-only).
|
|
4
|
+
*
|
|
5
|
+
* type ProviderType = 'intake' | 'issue' | 'vcs' | 'ci' | 'notify' | 'kb' | 'api' | 'observability'
|
|
6
|
+
*
|
|
7
|
+
* interface Provider {
|
|
8
|
+
* name: string
|
|
9
|
+
* type: ProviderType
|
|
10
|
+
* driver: string
|
|
11
|
+
* validate(): Promise<{ ok: boolean; reason?: string; needsLogin?: boolean }>
|
|
12
|
+
* login?({ force }): Promise<void>
|
|
13
|
+
* logout?(): Promise<void>
|
|
14
|
+
* }
|
|
15
|
+
*
|
|
16
|
+
* IntakeProvider extends Provider:
|
|
17
|
+
* fetch(url): { title, body_md, attachments[], source: { type, ref } }
|
|
18
|
+
* search?(q): SearchHit[]
|
|
19
|
+
* supports(input): boolean // does this provider know how to handle this input
|
|
20
|
+
*
|
|
21
|
+
* IssueProvider:
|
|
22
|
+
* fetch(id): { title, body_md, status, labels, source }
|
|
23
|
+
*
|
|
24
|
+
* KbProvider:
|
|
25
|
+
* upload(file, meta): { uuid, url? }
|
|
26
|
+
* update(uuid, file, meta): void
|
|
27
|
+
* delete(uuid): void
|
|
28
|
+
* search(q, opts?): SearchHit[]
|
|
29
|
+
*
|
|
30
|
+
* NotifyProvider:
|
|
31
|
+
* send({ subject, body_md, to, links[] }): { id }
|
|
32
|
+
*
|
|
33
|
+
* CiProvider:
|
|
34
|
+
* trigger(job, params): { runId, url }
|
|
35
|
+
* status(runId): { status, url, log? }
|
|
36
|
+
*
|
|
37
|
+
* ApiProvider:
|
|
38
|
+
* syncContract({ file, content, dryRun? }): { status, interfaces, url? }
|
|
39
|
+
*
|
|
40
|
+
* ObservabilityProvider:
|
|
41
|
+
* query({ query, traceId, requestId, since, limit }): { status, items[], url? }
|
|
42
|
+
*
|
|
43
|
+
* VcsProvider:
|
|
44
|
+
* pr({ title, body_md, base, head, draft? }): { url, number }
|
|
45
|
+
*/
|
|
46
|
+
|
|
47
|
+
class Provider {
|
|
48
|
+
constructor({ name, type, driver, config }) {
|
|
49
|
+
this.name = name;
|
|
50
|
+
this.type = type;
|
|
51
|
+
this.driver = driver;
|
|
52
|
+
this.config = config || {};
|
|
53
|
+
}
|
|
54
|
+
async validate() { return { ok: true }; }
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
class ProviderError extends Error {
|
|
58
|
+
constructor(message, { provider, code, retryable } = {}) {
|
|
59
|
+
super(message);
|
|
60
|
+
this.name = 'ProviderError';
|
|
61
|
+
this.provider = provider;
|
|
62
|
+
this.code = code;
|
|
63
|
+
this.retryable = !!retryable;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
class AuthExpiredError extends ProviderError {
|
|
68
|
+
constructor(message, opts = {}) {
|
|
69
|
+
super(message, { ...opts, code: 'auth_expired', retryable: true });
|
|
70
|
+
this.name = 'AuthExpiredError';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
module.exports = { Provider, ProviderError, AuthExpiredError };
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const http = require('http');
|
|
3
|
+
const https = require('https');
|
|
4
|
+
const { Provider } = require('../base.js');
|
|
5
|
+
|
|
6
|
+
class YapiProvider extends Provider {
|
|
7
|
+
async validate() {
|
|
8
|
+
if (!this.config.baseUrl) return { ok: false, reason: 'baseUrl missing' };
|
|
9
|
+
if (!this.config.token) return { ok: false, reason: 'token missing', needsLogin: true };
|
|
10
|
+
return { ok: true };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async syncContract({ file, content, dryRun = false } = {}) {
|
|
14
|
+
const summary = summarizeContract(content, file);
|
|
15
|
+
if (dryRun) return { status: 'dry-run', ...summary };
|
|
16
|
+
const payload = {
|
|
17
|
+
type: this.config.importType || 'swagger',
|
|
18
|
+
token: this.config.token,
|
|
19
|
+
project_id: this.config.projectId,
|
|
20
|
+
catid: this.config.categoryId,
|
|
21
|
+
merge: this.config.merge || 'normal',
|
|
22
|
+
json: content,
|
|
23
|
+
};
|
|
24
|
+
const res = await postJson(joinUrl(this.config.baseUrl, this.config.syncPath || '/api/open/import_data'), payload);
|
|
25
|
+
return { status: 'synced', ...summary, response: res };
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function summarizeContract(content = '', file = '') {
|
|
30
|
+
let interfaces = 0;
|
|
31
|
+
let title = file || 'contract';
|
|
32
|
+
try {
|
|
33
|
+
const json = JSON.parse(content);
|
|
34
|
+
title = json.info && json.info.title ? json.info.title : title;
|
|
35
|
+
if (json.paths && typeof json.paths === 'object') {
|
|
36
|
+
for (const item of Object.values(json.paths)) {
|
|
37
|
+
interfaces += Object.keys(item || {}).filter((k) => /^(get|post|put|patch|delete|head|options)$/i.test(k)).length;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
interfaces = (content.match(/^#{2,4}\s+/gm) || []).length;
|
|
42
|
+
}
|
|
43
|
+
return { title, interfaces, file };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function joinUrl(base, p) {
|
|
47
|
+
return String(base || '').replace(/\/+$/, '') + '/' + String(p || '').replace(/^\/+/, '');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function postJson(url, payload) {
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
const u = new URL(url);
|
|
53
|
+
const body = JSON.stringify(payload);
|
|
54
|
+
const lib = u.protocol === 'https:' ? https : http;
|
|
55
|
+
const req = lib.request({
|
|
56
|
+
method: 'POST',
|
|
57
|
+
hostname: u.hostname,
|
|
58
|
+
port: u.port || (u.protocol === 'https:' ? 443 : 80),
|
|
59
|
+
path: u.pathname + u.search,
|
|
60
|
+
headers: {
|
|
61
|
+
'content-type': 'application/json',
|
|
62
|
+
'content-length': Buffer.byteLength(body),
|
|
63
|
+
},
|
|
64
|
+
timeout: 15000,
|
|
65
|
+
}, (res) => {
|
|
66
|
+
let data = '';
|
|
67
|
+
res.setEncoding('utf8');
|
|
68
|
+
res.on('data', (chunk) => { data += chunk; });
|
|
69
|
+
res.on('end', () => resolve({ statusCode: res.statusCode, body: data.slice(0, 4000) }));
|
|
70
|
+
});
|
|
71
|
+
req.on('error', reject);
|
|
72
|
+
req.on('timeout', () => req.destroy(new Error('YAPI sync timeout')));
|
|
73
|
+
req.write(body);
|
|
74
|
+
req.end();
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
module.exports = { default: YapiProvider, _internals: { summarizeContract } };
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
const { Provider } = require('../base.js');
|
|
3
|
+
|
|
4
|
+
class JenkinsProvider extends Provider {
|
|
5
|
+
constructor(opts) {
|
|
6
|
+
super(opts);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
async validate() {
|
|
10
|
+
return { ok: true };
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async trigger(job, params = {}) {
|
|
14
|
+
const cleanParams = stripEmpty(params);
|
|
15
|
+
const buildUrl = toBuildUrl(resolveJobUrl(job, this.config), cleanParams);
|
|
16
|
+
const mode = (this.config.triggerMethod || 'post').toLowerCase();
|
|
17
|
+
const headers = {};
|
|
18
|
+
const auth = authHeader(this.config);
|
|
19
|
+
if (auth) headers.authorization = auth;
|
|
20
|
+
|
|
21
|
+
let url = buildUrl;
|
|
22
|
+
const init = { method: mode === 'get' ? 'GET' : 'POST', headers };
|
|
23
|
+
if (mode === 'get') {
|
|
24
|
+
url = withParams(buildUrl, cleanParams);
|
|
25
|
+
} else if (Object.keys(cleanParams).length) {
|
|
26
|
+
headers['content-type'] = 'application/x-www-form-urlencoded';
|
|
27
|
+
init.body = new URLSearchParams(cleanParams).toString();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
let res = await fetch(url, init);
|
|
31
|
+
if (!res.ok && res.status === 400 && mode !== 'get' && Object.keys(cleanParams).length) {
|
|
32
|
+
const retryHeaders = { ...headers };
|
|
33
|
+
delete retryHeaders['content-type'];
|
|
34
|
+
res = await fetch(url, { method: 'POST', headers: retryHeaders });
|
|
35
|
+
}
|
|
36
|
+
if (!res.ok && res.status !== 201) {
|
|
37
|
+
throw new Error(`jenkins trigger failed: HTTP ${res.status}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const queueUrl = res.headers.get('location') || null;
|
|
41
|
+
return {
|
|
42
|
+
runId: queueUrl || url,
|
|
43
|
+
url: queueUrl || url,
|
|
44
|
+
queueUrl,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async status(runId) {
|
|
49
|
+
if (!runId || !/^https?:\/\//i.test(String(runId))) {
|
|
50
|
+
return { status: 'unknown', url: null };
|
|
51
|
+
}
|
|
52
|
+
const apiUrl = String(runId).replace(/\/+$/, '') + '/api/json';
|
|
53
|
+
const headers = {};
|
|
54
|
+
const auth = authHeader(this.config);
|
|
55
|
+
if (auth) headers.authorization = auth;
|
|
56
|
+
const res = await fetch(apiUrl, { headers });
|
|
57
|
+
if (!res.ok) return { status: 'unknown', url: String(runId) };
|
|
58
|
+
const json = await res.json();
|
|
59
|
+
if (json.executable && json.executable.url) {
|
|
60
|
+
return { status: 'queued', url: json.executable.url, runId: String(json.executable.number || '') };
|
|
61
|
+
}
|
|
62
|
+
if (json.building) return { status: 'running', url: json.url || String(runId) };
|
|
63
|
+
if (json.result) return { status: String(json.result).toLowerCase(), url: json.url || String(runId) };
|
|
64
|
+
return { status: 'unknown', url: json.url || String(runId) };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function resolveJobUrl(job, config = {}) {
|
|
69
|
+
if (/^https?:\/\//i.test(String(job))) return String(job);
|
|
70
|
+
const base = String(config.baseUrl || '').replace(/\/+$/, '');
|
|
71
|
+
if (!base) throw new Error('jenkins job must be URL when config.baseUrl is not set');
|
|
72
|
+
return `${base}/job/${encodeURIComponent(String(job))}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function toBuildUrl(jobUrl, params = {}) {
|
|
76
|
+
const u = String(jobUrl).trim();
|
|
77
|
+
const hasParams = Object.keys(stripEmpty(params)).length > 0;
|
|
78
|
+
if (/\/buildWithParameters(?:\?|$)/.test(u)) return u;
|
|
79
|
+
if (/\/build(?:\?|$)/.test(u)) {
|
|
80
|
+
return hasParams ? u.replace(/\/build(?=\?|$)/, '/buildWithParameters') : u;
|
|
81
|
+
}
|
|
82
|
+
const endpoint = hasParams ? 'buildWithParameters' : 'build';
|
|
83
|
+
return u.replace(/\/+$/, '') + `/${endpoint}`;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function withParams(url, params = {}) {
|
|
87
|
+
const u = new URL(url);
|
|
88
|
+
for (const [k, v] of Object.entries(stripEmpty(params))) {
|
|
89
|
+
u.searchParams.set(k, String(v));
|
|
90
|
+
}
|
|
91
|
+
return u.toString();
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function stripEmpty(params) {
|
|
95
|
+
const out = {};
|
|
96
|
+
for (const [k, v] of Object.entries(params || {})) {
|
|
97
|
+
if (v !== undefined && v !== null && v !== '') out[k] = v;
|
|
98
|
+
}
|
|
99
|
+
return out;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function authHeader(config = {}) {
|
|
103
|
+
if (!config.user && !config.token) return null;
|
|
104
|
+
return 'Basic ' + Buffer.from(`${config.user || ''}:${config.token || ''}`).toString('base64');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
JenkinsProvider._internals = { resolveJobUrl, toBuildUrl, withParams, stripEmpty };
|
|
108
|
+
|
|
109
|
+
module.exports = { default: JenkinsProvider };
|