@pipeline-builder/api-core 4.1.13 → 4.1.15
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/README.md +3 -2
- package/lib/constants/index.d.ts +0 -1
- package/lib/constants/index.js +1 -2
- package/lib/errors/app-errors.d.ts +8 -3
- package/lib/errors/app-errors.js +10 -5
- package/lib/helpers/access-helpers.d.ts +4 -6
- package/lib/helpers/access-helpers.js +6 -8
- package/lib/helpers/index.d.ts +3 -3
- package/lib/helpers/index.js +4 -4
- package/lib/helpers/org-hierarchy-http.d.ts +11 -10
- package/lib/helpers/org-hierarchy-http.js +24 -35
- package/lib/helpers/org-hierarchy.d.ts +37 -3
- package/lib/helpers/org-hierarchy.js +45 -4
- package/lib/helpers/restore-helpers.d.ts +44 -24
- package/lib/helpers/restore-helpers.js +41 -52
- package/lib/helpers/sse-helpers.d.ts +29 -7
- package/lib/helpers/sse-helpers.js +36 -9
- package/lib/index.d.ts +16 -14
- package/lib/index.js +17 -15
- package/lib/middleware/assurance.d.ts +116 -0
- package/lib/middleware/assurance.js +176 -0
- package/lib/middleware/auth.d.ts +5 -427
- package/lib/middleware/auth.js +36 -789
- package/lib/middleware/ecosystem-guard.d.ts +47 -0
- package/lib/middleware/ecosystem-guard.js +60 -0
- package/lib/middleware/index.d.ts +11 -4
- package/lib/middleware/index.js +12 -5
- package/lib/middleware/jwt-verify.d.ts +52 -0
- package/lib/middleware/jwt-verify.js +105 -0
- package/lib/middleware/permission-gates.d.ts +133 -0
- package/lib/middleware/permission-gates.js +260 -0
- package/lib/middleware/revocation.d.ts +96 -0
- package/lib/middleware/revocation.js +162 -0
- package/lib/middleware/route-table.d.ts +11 -0
- package/lib/middleware/route-table.js +4 -1
- package/lib/middleware/service-tokens.d.ts +83 -0
- package/lib/middleware/service-tokens.js +158 -0
- package/lib/middleware/step-up.d.ts +2 -2
- package/lib/middleware/step-up.js +8 -7
- package/lib/middleware/system-org.d.ts +20 -0
- package/lib/middleware/system-org.js +25 -0
- package/lib/openapi/routes/plugin-routes.js +133 -10
- package/lib/openapi/schema-registry.js +2 -5
- package/lib/routes/index.d.ts +1 -1
- package/lib/routes/index.js +2 -2
- package/lib/services/api-key-exchange.js +7 -5
- package/lib/services/audit-spool.d.ts +34 -10
- package/lib/services/audit-spool.js +75 -34
- package/lib/services/cache-service.d.ts +7 -0
- package/lib/services/cache-service.js +1 -1
- package/lib/services/circuit-breaker.d.ts +14 -1
- package/lib/services/circuit-breaker.js +36 -10
- package/lib/services/compliance-client.d.ts +10 -2
- package/lib/services/compliance-client.js +17 -10
- package/lib/services/compliance-event-subscriber.js +6 -6
- package/lib/services/durable-event-bus.js +8 -11
- package/lib/services/ecosystem-notify-client.d.ts +32 -0
- package/lib/services/ecosystem-notify-client.js +71 -0
- package/lib/services/env-redis.d.ts +4 -1
- package/lib/services/env-redis.js +32 -3
- package/lib/services/http-client.d.ts +19 -0
- package/lib/services/http-client.js +98 -19
- package/lib/services/index.d.ts +25 -24
- package/lib/services/index.js +25 -22
- package/lib/services/jwks-cache.js +5 -4
- package/lib/services/leader-lock.d.ts +22 -5
- package/lib/services/leader-lock.js +61 -6
- package/lib/services/quota.d.ts +9 -4
- package/lib/services/quota.js +34 -40
- package/lib/services/remote-audit-client.d.ts +28 -32
- package/lib/services/remote-audit-client.js +166 -49
- package/lib/services/retry-forever.js +5 -11
- package/lib/services/retry-strategy.d.ts +1 -1
- package/lib/services/retry-strategy.js +5 -4
- package/lib/services/scheduler.d.ts +8 -3
- package/lib/services/scheduler.js +17 -5
- package/lib/services/service-boot.d.ts +14 -13
- package/lib/services/service-boot.js +18 -15
- package/lib/services/service-keys.d.ts +1 -1
- package/lib/services/service-keys.js +12 -18
- package/lib/services/sse-ticket-store.d.ts +9 -1
- package/lib/services/sse-ticket-store.js +24 -9
- package/lib/services/system-notification.d.ts +27 -0
- package/lib/services/system-notification.js +50 -0
- package/lib/services/token-revocation.d.ts +50 -1
- package/lib/services/token-revocation.js +103 -3
- package/lib/types/audit-events.d.ts +6 -6
- package/lib/types/audit-events.js +1 -1
- package/lib/types/common.d.ts +32 -13
- package/lib/types/common.js +2 -1
- package/lib/types/ecosystem-notifications.d.ts +142 -0
- package/lib/types/ecosystem-notifications.js +210 -0
- package/lib/types/ecosystem.d.ts +77 -0
- package/lib/types/ecosystem.js +119 -0
- package/lib/types/error-codes.d.ts +81 -0
- package/lib/types/error-codes.js +108 -1
- package/lib/types/feature-flags.d.ts +21 -1
- package/lib/types/feature-flags.js +36 -2
- package/lib/types/index.d.ts +14 -9
- package/lib/types/index.js +15 -10
- package/lib/types/permissions.d.ts +46 -8
- package/lib/types/permissions.js +75 -12
- package/lib/types/plugin-catalog.d.ts +35 -0
- package/lib/types/plugin-catalog.js +39 -0
- package/lib/types/plugin-health.d.ts +102 -0
- package/lib/types/plugin-health.js +184 -0
- package/lib/types/quota-tiers.d.ts +15 -0
- package/lib/types/quota-tiers.js +23 -3
- package/lib/types/wire-vocabulary.d.ts +102 -0
- package/lib/types/wire-vocabulary.js +94 -0
- package/lib/utils/alias-resolver.js +2 -2
- package/lib/utils/audit.d.ts +5 -2
- package/lib/utils/audit.js +6 -3
- package/lib/utils/compliance-attributes.js +3 -4
- package/lib/utils/concurrency.d.ts +7 -0
- package/lib/utils/concurrency.js +13 -1
- package/lib/utils/env.d.ts +3 -4
- package/lib/utils/env.js +4 -5
- package/lib/utils/identity.d.ts +13 -4
- package/lib/utils/identity.js +18 -10
- package/lib/utils/index.d.ts +13 -10
- package/lib/utils/index.js +13 -10
- package/lib/utils/jwk.d.ts +4 -0
- package/lib/utils/jwk.js +13 -1
- package/lib/utils/logger.d.ts +1 -1
- package/lib/utils/logger.js +1 -1
- package/lib/utils/object.d.ts +11 -0
- package/lib/utils/object.js +24 -1
- package/lib/utils/params.d.ts +8 -22
- package/lib/utils/params.js +15 -43
- package/lib/utils/plugin-compliance.d.ts +98 -0
- package/lib/utils/plugin-compliance.js +78 -0
- package/lib/utils/proof-of-work.d.ts +69 -0
- package/lib/utils/proof-of-work.js +139 -0
- package/lib/utils/response.d.ts +16 -6
- package/lib/utils/response.js +18 -15
- package/lib/utils/retention.d.ts +17 -0
- package/lib/utils/retention.js +30 -0
- package/lib/utils/secret-encryption.d.ts +7 -7
- package/lib/utils/secret-encryption.js +9 -10
- package/lib/utils/secret-rotation.js +2 -2
- package/lib/utils/sensitive-patterns.js +4 -5
- package/lib/utils/service-registry.d.ts +15 -0
- package/lib/utils/service-registry.js +24 -0
- package/lib/utils/ssrf.d.ts +11 -2
- package/lib/utils/ssrf.js +112 -33
- package/lib/validation/ai-schemas.js +3 -2
- package/lib/validation/common-schemas.d.ts +0 -9
- package/lib/validation/common-schemas.js +1 -7
- package/lib/validation/dockerfile-static.d.ts +26 -0
- package/lib/validation/dockerfile-static.js +210 -0
- package/lib/validation/index.d.ts +13 -4
- package/lib/validation/index.js +14 -5
- package/lib/validation/message-schemas.js +6 -4
- package/lib/validation/pipeline-schemas.d.ts +8 -2
- package/lib/validation/pipeline-schemas.js +30 -4
- package/lib/validation/plugin-base-images.d.ts +20 -0
- package/lib/validation/plugin-base-images.js +17 -0
- package/lib/validation/plugin-catalog-detect.d.ts +86 -0
- package/lib/validation/plugin-catalog-detect.js +237 -0
- package/lib/validation/plugin-catalog-metadata.d.ts +141 -0
- package/lib/validation/plugin-catalog-metadata.js +162 -0
- package/lib/validation/plugin-heuristics.d.ts +41 -0
- package/lib/validation/plugin-heuristics.js +211 -0
- package/lib/validation/plugin-lint.d.ts +18 -0
- package/lib/validation/plugin-lint.js +136 -0
- package/lib/validation/plugin-name-confusable.d.ts +15 -0
- package/lib/validation/plugin-name-confusable.js +81 -0
- package/lib/validation/plugin-schemas.d.ts +40 -26
- package/lib/validation/plugin-schemas.js +26 -23
- package/lib/validation/plugin-spec-schema.d.ts +112 -0
- package/lib/validation/plugin-spec-schema.js +163 -0
- package/lib/validation/plugin-template-contract.d.ts +64 -0
- package/lib/validation/plugin-template-contract.js +113 -0
- package/package.json +69 -4
- package/lib/testing/mock-api-core.d.ts +0 -150
- package/lib/testing/mock-api-core.js +0 -246
- package/lib/testing/mock-drizzle.d.ts +0 -6
- package/lib/testing/mock-drizzle.js +0 -57
- package/lib/testing/route-coverage.d.ts +0 -64
- package/lib/testing/route-coverage.js +0 -183
- package/lib/testing/service-tokens.d.ts +0 -66
- package/lib/testing/service-tokens.js +0 -137
- package/lib/testing/tier-mock.d.ts +0 -44
- package/lib/testing/tier-mock.js +0 -65
- package/lib/testing/user-tokens.d.ts +0 -75
- package/lib/testing/user-tokens.js +0 -115
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* The catalog's STATIC plugin checks (deploy/bin/test-plugins.sh), for a plugin
|
|
5
|
+
* directory outside the repo: the spec fields the catalog tooling requires and
|
|
6
|
+
* the Dockerfile rules (deploy/plugins/README.md "Dockerfile rules"). Shared
|
|
7
|
+
* from api-core so the CLI (`plugin validate --lint`, `plugin publish`) and the
|
|
8
|
+
* plugin service (AI generation) apply ONE implementation (plugin-ecosystem W6):
|
|
9
|
+
*
|
|
10
|
+
* - the final stage ends as a non-root `USER`, set in the plugin's own Dockerfile;
|
|
11
|
+
* - every download goes through `fetch-verified` (no raw curl/wget, no `ADD <url>`
|
|
12
|
+
* without `--checksum=`);
|
|
13
|
+
* - no pipe-to-shell installers;
|
|
14
|
+
* - no secrets in `ENV`/`ARG`; apt caches cleaned; a `WORKDIR`;
|
|
15
|
+
* - the spec never downloads a tool at runtime.
|
|
16
|
+
*
|
|
17
|
+
* Only the repo-layout rules (name = directory, category = parent directory)
|
|
18
|
+
* are left to test-plugins.sh: a publisher's plugin doesn't live in that tree.
|
|
19
|
+
* Warnings never fail; errors do.
|
|
20
|
+
*/
|
|
21
|
+
import { parseDockerfile } from './dockerfile-static.js';
|
|
22
|
+
/** Spec fields test-plugins.sh requires on every plugin. */
|
|
23
|
+
export const PLUGIN_LINT_REQUIRED_FIELDS = ['name', 'description', 'keywords', 'category', 'version', 'pluginType', 'computeType', 'timeout', 'failureBehavior', 'secrets'];
|
|
24
|
+
/** …and on every CodeBuildStep. */
|
|
25
|
+
export const PLUGIN_LINT_CODEBUILD_FIELDS = ['primaryOutputDirectory', 'dockerfile', 'installCommands', 'commands'];
|
|
26
|
+
/** Logical Dockerfile instructions: comment lines dropped, `\` continuations joined. */
|
|
27
|
+
export function dockerfileInstructions(content) {
|
|
28
|
+
const out = [];
|
|
29
|
+
let buf = '';
|
|
30
|
+
for (const raw of content.replace(/\r\n?/g, '\n').split('\n')) {
|
|
31
|
+
if (/^\s*#/.test(raw))
|
|
32
|
+
continue;
|
|
33
|
+
if (/\\\s*$/.test(raw)) {
|
|
34
|
+
buf += `${raw.replace(/\\\s*$/, '')} `;
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
buf += raw;
|
|
38
|
+
if (/\S/.test(buf))
|
|
39
|
+
out.push(buf.trim());
|
|
40
|
+
buf = '';
|
|
41
|
+
}
|
|
42
|
+
if (/\S/.test(buf))
|
|
43
|
+
out.push(buf.trim());
|
|
44
|
+
return out;
|
|
45
|
+
}
|
|
46
|
+
const instructionOf = (line) => (/^(\S+)/.exec(line)?.[1] ?? '').toUpperCase();
|
|
47
|
+
/** RUN instructions that pipe into a shell (`curl … | bash`). */
|
|
48
|
+
export function pipeInstallers(content) {
|
|
49
|
+
return dockerfileInstructions(content).filter(l => instructionOf(l) === 'RUN' && /(^|[^|])\|\s*(sudo\s+)?(\/usr)?(\/bin\/)?(ba|da|z|k)?sh(\s|$)/.test(l));
|
|
50
|
+
}
|
|
51
|
+
/** curl/wget DOWNLOADS in RUN, and `ADD <url>` without `--checksum=`. */
|
|
52
|
+
export function rawDownloads(content) {
|
|
53
|
+
const found = [];
|
|
54
|
+
for (const line of dockerfileInstructions(content)) {
|
|
55
|
+
const instr = instructionOf(line);
|
|
56
|
+
if (instr === 'ADD' && /https?:\/\//.test(line) && !/--checksum=/.test(line)) {
|
|
57
|
+
found.push(`ADD ${line}`);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
if (instr !== 'RUN')
|
|
61
|
+
continue;
|
|
62
|
+
const body = line.replace(/^\s*run\s+/i, '');
|
|
63
|
+
for (let part of body.split(/&&|\|\||;|\||\$\(|`|\(|\{/)) {
|
|
64
|
+
for (;;) {
|
|
65
|
+
part = part.replace(/^\s+/, '');
|
|
66
|
+
const prefix = /^(if|then|do|else|elif|while|until|!|sudo|exec|command|time|--[a-z-]+(=\S*)?|[A-Za-z_][A-Za-z0-9_]*=\S*)\s+/.exec(part);
|
|
67
|
+
if (!prefix)
|
|
68
|
+
break;
|
|
69
|
+
part = part.slice(prefix[0].length);
|
|
70
|
+
}
|
|
71
|
+
if (/^(curl|wget)(\s|$)/.test(part) && (/:\/\//.test(part) || /\$/.test(part) || /\s(-o|-O|--output|--output-document)([\s=]|$)/.test(part))) {
|
|
72
|
+
found.push(part.trim());
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return found;
|
|
77
|
+
}
|
|
78
|
+
/** Lint a Dockerfile against the catalog's rules. */
|
|
79
|
+
export function lintPluginDockerfile(content) {
|
|
80
|
+
const findings = [];
|
|
81
|
+
const err = (message) => findings.push({ level: 'error', message });
|
|
82
|
+
const instructions = dockerfileInstructions(content);
|
|
83
|
+
if (!instructions.some(l => instructionOf(l) === 'FROM')) {
|
|
84
|
+
err('Dockerfile: missing FROM instruction');
|
|
85
|
+
return findings;
|
|
86
|
+
}
|
|
87
|
+
if (!instructions.some(l => instructionOf(l) === 'WORKDIR'))
|
|
88
|
+
err('Dockerfile: missing WORKDIR instruction');
|
|
89
|
+
if (/^(ENV|ARG)\s+(.*TOKEN|.*SECRET|.*PASSWORD|.*API_KEY|.*PRIVATE_KEY)/m.test(content)) {
|
|
90
|
+
err('Dockerfile: potential secret in an ENV/ARG instruction (pass secrets at run time via the spec\'s `secrets`)');
|
|
91
|
+
}
|
|
92
|
+
const finalUser = parseDockerfile(content).finalUser;
|
|
93
|
+
const userPart = (finalUser ?? '').split(':')[0];
|
|
94
|
+
if (!finalUser)
|
|
95
|
+
err('Dockerfile: the final stage sets no USER (end with `USER 1000:1000`)');
|
|
96
|
+
else if (userPart === 'root' || userPart === '0')
|
|
97
|
+
err(`Dockerfile: the final stage runs as root (USER ${finalUser}); end with \`USER 1000:1000\``);
|
|
98
|
+
const pipes = pipeInstallers(content);
|
|
99
|
+
if (pipes.length)
|
|
100
|
+
err(`Dockerfile: pipes a download into a shell (use a pinned release via fetch-verified, a fetch-apt-key apt repo, or an ecosystem base): ${pipes[0].slice(0, 160)}`);
|
|
101
|
+
const downloads = rawDownloads(content);
|
|
102
|
+
if (downloads.length)
|
|
103
|
+
err(`Dockerfile: raw download not via fetch-verified: ${downloads[0].slice(0, 160)}`);
|
|
104
|
+
if (/apt-get install/.test(content) && !/rm -rf \/var\/lib\/apt\/lists/.test(content)) {
|
|
105
|
+
err('Dockerfile: missing apt cache cleanup (rm -rf /var/lib/apt/lists/*)');
|
|
106
|
+
}
|
|
107
|
+
return findings;
|
|
108
|
+
}
|
|
109
|
+
/** Lint the spec document (as parsed) the way test-plugins.sh does. */
|
|
110
|
+
export function lintPluginSpec(spec, specText) {
|
|
111
|
+
const findings = [];
|
|
112
|
+
const err = (message) => findings.push({ level: 'error', message });
|
|
113
|
+
for (const f of PLUGIN_LINT_REQUIRED_FIELDS)
|
|
114
|
+
if (!(f in spec))
|
|
115
|
+
err(`plugin-spec.yaml: missing required field: ${f}`);
|
|
116
|
+
if (spec.pluginType === 'CodeBuildStep' || spec.pluginType === undefined) {
|
|
117
|
+
for (const f of PLUGIN_LINT_CODEBUILD_FIELDS)
|
|
118
|
+
if (!(f in spec))
|
|
119
|
+
err(`plugin-spec.yaml: missing CodeBuild field: ${f}`);
|
|
120
|
+
}
|
|
121
|
+
if (typeof spec.version === 'string' && !/^\d+\.\d+\.\d+$/.test(spec.version)) {
|
|
122
|
+
err(`plugin-spec.yaml: catalog versions are plain semver x.y.z (got ${spec.version})`);
|
|
123
|
+
}
|
|
124
|
+
if (typeof spec.description !== 'string' || spec.description.trim() === '')
|
|
125
|
+
err('plugin-spec.yaml: empty description');
|
|
126
|
+
if ('keywords' in spec && (!Array.isArray(spec.keywords) || spec.keywords.length === 0))
|
|
127
|
+
err('plugin-spec.yaml: empty keywords list');
|
|
128
|
+
const download = /(curl|wget)\s.*https?:\/\/[^\s"]*(releases\/download\/|\.tar\.gz|\.tgz|\.tar\.xz|\.zip)/.exec(specText);
|
|
129
|
+
if (download)
|
|
130
|
+
err(`plugin-spec.yaml: downloads a tool at runtime (bake it into the image via fetch-verified): ${download[0].slice(0, 160)}`);
|
|
131
|
+
if (/^\s*- \|/m.test(specText) && !/set -e/.test(specText)) {
|
|
132
|
+
findings.push({ level: 'warning', message: 'plugin-spec.yaml: multi-line command(s) without `set -e` — intermediate failures will silently pass' });
|
|
133
|
+
}
|
|
134
|
+
return findings;
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLWxpbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmFsaWRhdGlvbi9wbHVnaW4tbGludC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDOzs7Ozs7Ozs7Ozs7Ozs7OztHQWlCRztBQUVILE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU96RCw0REFBNEQ7QUFDNUQsTUFBTSxDQUFDLE1BQU0sMkJBQTJCLEdBQXNCLENBQUMsTUFBTSxFQUFFLGFBQWEsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxZQUFZLEVBQUUsYUFBYSxFQUFFLFNBQVMsRUFBRSxpQkFBaUIsRUFBRSxTQUFTLENBQUMsQ0FBQztBQUMvTCxtQ0FBbUM7QUFDbkMsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQXNCLENBQUMsd0JBQXdCLEVBQUUsWUFBWSxFQUFFLGlCQUFpQixFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBRXZJLHdGQUF3RjtBQUN4RixNQUFNLFVBQVUsc0JBQXNCLENBQUMsT0FBZTtJQUNwRCxNQUFNLEdBQUcsR0FBYSxFQUFFLENBQUM7SUFDekIsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBQ2IsS0FBSyxNQUFNLEdBQUcsSUFBSSxPQUFPLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUM5RCxJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQUUsU0FBUztRQUNoQyxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN2QixHQUFHLElBQUksR0FBRyxHQUFHLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsR0FBRyxDQUFDO1lBQ3ZDLFNBQVM7UUFDWCxDQUFDO1FBQ0QsR0FBRyxJQUFJLEdB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QUNELElBQUksT0FBTyxJQUFJLENBQUMsT0FBTyxLQUFLLFFBQVEsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUM5RSxHQUFHLENBQUMsa0VBQWtFLElBQUksQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO0lBQ3pGLENBQUM7SUFDRCxJQUFJLE9BQU8sSUFBSSxDQUFDLFdBQVcsS0FBSyxRQUFRLElBQUksSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEVBQUUsS0FBSyxFQUFFO1FBQUUsR0FBRyxDQUFDLHFDQUFxQyxDQUFDLENBQUM7SUFDdkgsSUFBSSxVQUFVLElBQUksSUFBSSxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUM7UUFBRSxHQUFHLENBQUMsdUNBQXVDLENBQUMsQ0FBQztJQUN0SSxNQUFNLFFBQVEsR0FBRyx5RkFBeUYsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDMUgsSUFBSSxRQUFRO1FBQUUsR0FBRyxDQUFDLDhGQUE4RixRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDN0ksSUFBSSxXQUFXLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQzNELFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxxR0FBcUcsRUFBRSxDQUFDLENBQUM7SUFDdEosQ0FBQztJQUNELE9BQU8sUUFBUSxDQUFDO0FBQ2xCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBUaGUgY2F0YWxvZydzIFNUQVRJQyBwbHVnaW4gY2hlY2tzIChkZXBsb3kvYmluL3Rlc3QtcGx1Z2lucy5zaCksIGZvciBhIHBsdWdpblxuICogZGlyZWN0b3J5IG91dHNpZGUgdGhlIHJlcG86IHRoZSBzcGVjIGZpZWxkcyB0aGUgY2F0YWxvZyB0b29saW5nIHJlcXVpcmVzIGFuZFxuICogdGhlIERvY2tlcmZpbGUgcnVsZXMgKGRlcGxveS9wbHVnaW5zL1JFQURNRS5tZCBcIkRvY2tlcmZpbGUgcnVsZXNcIikuIFNoYXJlZFxuICogZnJvbSBhcGktY29yZSBzbyB0aGUgQ0xJIChgcGx1Z2luIHZhbGlkYXRlIC0tbGludGAsIGBwbHVnaW4gcHVibGlzaGApIGFuZCB0aGVcbiAqIHBsdWdpbiBzZXJ2aWNlIChBSSBnZW5lcmF0aW9uKSBhcHBseSBPTkUgaW1wbGVtZW50YXRpb24gKHBsdWdpbi1lY29zeXN0ZW0gVzYpOlxuICpcbiAqICAtIHRoZSBmaW5hbCBzdGFnZSBlbmRzIGFzIGEgbm9uLXJvb3QgYFVTRVJgLCBzZXQgaW4gdGhlIHBsdWdpbidzIG93biBEb2NrZXJmaWxlO1xuICogIC0gZXZlcnkgZG93bmxvYWQgZ29lcyB0aHJvdWdoIGBmZXRjaC12ZXJpZmllZGAgKG5vIHJhdyBjdXJsL3dnZXQsIG5vIGBBREQgPHVybD5gXG4gKiAgICB3aXRob3V0IGAtLWNoZWNrc3VtPWApO1xuICogIC0gbm8gcGlwZS10by1zaGVsbCBpbnN0YWxsZXJzO1xuICogIC0gbm8gc2VjcmV0cyBpbiBgRU5WYC9gQVJHYDsgYXB0IGNhY2hlcyBjbGVhbmVkOyBhIGBXT1JLRElSYDtcbiAqICAtIHRoZSBzcGVjIG5ldmVyIGRvd25sb2FkcyBhIHRvb2wgYXQgcnVudGltZS5cbiAqXG4gKiBPbmx5IHRoZSByZXBvLWxheW91dCBydWxlcyAobmFtZSA9IGRpcmVjdG9yeSwgY2F0ZWdvcnkgPSBwYXJlbnQgZGlyZWN0b3J5KVxuICogYXJlIGxlZnQgdG8gdGVzdC1wbHVnaW5zLnNoOiBhIHB1Ymxpc2hlcidzIHBsdWdpbiBkb2Vzbid0IGxpdmUgaW4gdGhhdCB0cmVlLlxuICogV2FybmluZ3MgbmV2ZXIgZmFpbDsgZXJyb3JzIGRvLlxuICovXG5cbmltcG9ydCB7IHBhcnNlRG9ja2VyZmlsZSB9IGZyb20gJy4vZG9ja2VyZmlsZS1zdGF0aWMuanMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFBsdWdpbkxpbnRGaW5kaW5nIHtcbiAgbGV2ZWw6ICdlcnJvcicgfCAnd2FybmluZyc7XG4gIG1lc3NhZ2U6IHN0cmluZztcbn1cblxuLyoqIFNwZWMgZmllbGRzIHRlc3QtcGx1Z2lucy5zaCByZXF1aXJlcyBvbiBldmVyeSBwbHVnaW4uICovXG5leHBvcnQgY29uc3QgUExVR0lOX0xJTlRfUkVRVUlSRURfRklFTERTOiByZWFkb25seSBzdHJpbmdbXSA9IFsnbmFtZScsICdkZXNjcmlwdGlvbicsICdrZXl3b3JkcycsICdjYXRlZ29yeScsICd2ZXJzaW9uJywgJ3BsdWdpblR5cGUnLCAnY29tcHV0ZVR5cGUnLCAndGltZW91dCcsICdmYWlsdXJlQmVoYXZpb3InLCAnc2VjcmV0cyddO1xuLyoqIOKApmFuZCBvbiBldmVyeSBDb2RlQnVpbGRTdGVwLiAqL1xuZXhwb3J0IGNvbnN0IFBMVUdJTl9MSU5UX0NPREVCVUlMRF9GSUVMRFM6IHJlYWRvbmx5IHN0cmluZ1tdID0gWydwcmltYXJ5T3V0cHV0RGlyZWN0b3J5JywgJ2RvY2tlcmZpbGUnLCAnaW5zdGFsbENvbW1hbmRzJywgJ2NvbW1hbmRzJ107XG5cbi8qKiBMb2dpY2FsIERvY2tlcmZpbGUgaW5zdHJ1Y3Rpb25zOiBjb21tZW50IGxpbmVzIGRyb3BwZWQsIGBcXGAgY29udGludWF0aW9ucyBqb2luZWQuICovXG5leHBvcnQgZnVuY3Rpb24gZG9ja2VyZmlsZUluc3RydWN0aW9ucyhjb250ZW50OiBzdHJpbmcpOiBzdHJpbmdbXSB7XG4gIGNvbnN0IG91dDogc3RyaW5nW10gPSBbXTtcbiAgbGV0IGJ1ZiA9ICcnO1xuICBmb3IgKGNvbnN0IHJhdyBvZiBjb250ZW50LnJlcGxhY2UoL1xcclxcbj8vZywgJ1xcbicpLnNwbGl0KCdcXG4nKSkge1xuICAgIGlmICgvXlxccyojLy50ZXN0KHJhdykpIGNvbnRpbnVlO1xuICAgIGlmICgvXFxcXFxccyokLy50ZXN0KHJhdykpIHtcbiAgICAgIGJ1ZiArPSBgJHtyYXcucmVwbGFjZSgvXFxcXFxccyokLywgJycpfSBgO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGJ1ZiArPSByYXc7XG4gICAgaWYgKC9cXFMvLnRlc3QoYnVmKSkgb3V0LnB1c2goYnVmLnRyaW0oKSk7XG4gICAgYnVmID0gJyc7XG4gIH1cbiAgaWYgKC9cXFMvLnRlc3QoYnVmKSkgb3V0LnB1c2goYnVmLnRyaW0oKSk7XG4gIHJldHVybiBvdXQ7XG59XG5cbmNvbnN0IGluc3RydWN0aW9uT2YgPSAobGluZTogc3RyaW5nKTogc3RyaW5nID0+ICgvXihcXFMrKS8uZXhlYyhsaW5lKT8uWzFdID8/ICcnKS50b1VwcGVyQ2FzZSgpO1xuXG4vKiogUlVOIGluc3RydWN0aW9ucyB0aGF0IHBpcGUgaW50byBhIHNoZWxsIChgY3VybCDigKYgfCBiYXNoYCkuICovXG5leHBvcnQgZnVuY3Rpb24gcGlwZUluc3RhbGxlcnMoY29udGVudDogc3RyaW5nKTogc3RyaW5nW10ge1xuICByZXR1cm4gZG9ja2VyZmlsZUluc3RydWN0aW9ucyhjb250ZW50KS5maWx0ZXIobCA9PlxuICAgIGluc3RydWN0aW9uT2YobCkgPT09ICdSVU4nICYmIC8oXnxbXnxdKVxcfFxccyooc3Vkb1xccyspPyhcXC91c3IpPyhcXC9iaW5cXC8pPyhiYXxkYXx6fGspP3NoKFxcc3wkKS8udGVzdChsKSk7XG59XG5cbi8qKiBjdXJsL3dnZXQgRE9XTkxPQURTIGluIFJVTiwgYW5kIGBBREQgPHVybD5gIHdpdGhvdXQgYC0tY2hlY2tzdW09YC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByYXdEb3dubG9hZHMoY29udGVudDogc3RyaW5nKTogc3RyaW5nW10ge1xuICBjb25zdCBmb3VuZDogc3RyaW5nW10gPSBbXTtcbiAgZm9yIChjb25zdCBsaW5lIG9mIGRvY2tlcmZpbGVJbnN0cnVjdGlvbnMoY29udGVudCkpIHtcbiAgICBjb25zdCBpbnN0ciA9IGluc3RydWN0aW9uT2YobGluZSk7XG4gICAgaWYgKGluc3RyID09PSAnQUREJyAmJiAvaHR0cHM/OlxcL1xcLy8udGVzdChsaW5lKSAmJiAhLy0tY2hlY2tzdW09Ly50ZXN0KGxpbmUpKSB7XG4gICAgICBmb3VuZC5wdXNoKGBBREQgJHtsaW5lfWApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuICAgIGlmIChpbnN0ciAhPT0gJ1JVTicpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGJvZHkgPSBsaW5lLnJlcGxhY2UoL15cXHMqcnVuXFxzKy9pLCAnJyk7XG4gICAgZm9yIChsZXQgcGFydCBvZiBib2R5LnNwbGl0KC8mJnxcXHxcXHx8O3xcXHx8XFwkXFwofGB8XFwofFxcey8pKSB7XG4gICAgICBmb3IgKDs7KSB7XG4gICAgICAgIHBhcnQgPSBwYXJ0LnJlcGxhY2UoL15cXHMrLywgJycpO1xuICAgICAgICBjb25zdCBwcmVmaXggPSAvXihpZnx0aGVufGRvfGVsc2V8ZWxpZnx3aGlsZXx1bnRpbHwhfHN1ZG98ZXhlY3xjb21tYW5kfHRpbWV8LS1bYS16LV0rKD1cXFMqKT98W0EtWmEtel9dW0EtWmEtejAtOV9dKj1cXFMqKVxccysvLmV4ZWMocGFydCk7XG4gICAgICAgIGlmICghcHJlZml4KSBicmVhaztcbiAgICAgICAgcGFydCA9IHBhcnQuc2xpY2UocHJlZml4WzBdLmxlbmd0aCk7XG4gICAgICB9XG4gICAgICBpZiAoL14oY3VybHx3Z2V0KShcXHN8JCkvLnRlc3QocGFydCkgJiYgKC86XFwvXFwvLy50ZXN0KHBhcnQpIHx8IC9cXCQvLnRlc3QocGFydCkgfHwgL1xccygtb3wtT3wtLW91dHB1dHwtLW91dHB1dC1kb2N1bWVudCkoW1xccz1dfCQpLy50ZXN0KHBhcnQpKSkge1xuICAgICAgICBmb3VuZC5wdXNoKHBhcnQudHJpbSgpKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGZvdW5kO1xufVxuXG4vKiogTGludCBhIERvY2tlcmZpbGUgYWdhaW5zdCB0aGUgY2F0YWxvZydzIHJ1bGVzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpbnRQbHVnaW5Eb2NrZXJmaWxlKGNvbnRlbnQ6IHN0cmluZyk6IFBsdWdpbkxpbnRGaW5kaW5nW10ge1xuICBjb25zdCBmaW5kaW5nczogUGx1Z2luTGludEZpbmRpbmdbXSA9IFtdO1xuICBjb25zdCBlcnIgPSAobWVzc2FnZTogc3RyaW5nKSA9PiBmaW5kaW5ncy5wdXNoKHsgbGV2ZWw6ICdlcnJvcicsIG1lc3NhZ2UgfSk7XG4gIGNvbnN0IGluc3RydWN0aW9ucyA9IGRvY2tlcmZpbGVJbnN0cnVjdGlvbnMoY29udGVudCk7XG4gIGlmICghaW5zdHJ1Y3Rpb25zLnNvbWUobCA9PiBpbnN0cnVjdGlvbk9mKGwpID09PSAnRlJPTScpKSB7XG4gICAgZXJyKCdEb2NrZXJmaWxlOiBtaXNzaW5nIEZST00gaW5zdHJ1Y3Rpb24nKTtcbiAgICByZXR1cm4gZmluZGluZ3M7XG4gIH1cbiAgaWYgKCFpbnN0cnVjdGlvbnMuc29tZShsID0+IGluc3RydWN0aW9uT2YobCkgPT09ICdXT1JLRElSJykpIGVycignRG9ja2VyZmlsZTogbWlzc2luZyBXT1JLRElSIGluc3RydWN0aW9uJyk7XG4gIGlmICgvXihFTlZ8QVJHKVxccysoLipUT0tFTnwuKlNFQ1JFVHwuKlBBU1NXT1JEfC4qQVBJX0tFWXwuKlBSSVZBVEVfS0VZKS9tLnRlc3QoY29udGVudCkpIHtcbiAgICBlcnIoJ0RvY2tlcmZpbGU6IHBvdGVudGlhbCBzZWNyZXQgaW4gYW4gRU5WL0FSRyBpbnN0cnVjdGlvbiAocGFzcyBzZWNyZXRzIGF0IHJ1biB0aW1lIHZpYSB0aGUgc3BlY1xcJ3MgYHNlY3JldHNgKScpO1xuICB9XG4gIGNvbnN0IGZpbmFsVXNlciA9IHBhcnNlRG9ja2VyZmlsZShjb250ZW50KS5maW5hbFVzZXI7XG4gIGNvbnN0IHVzZXJQYXJ0ID0gKGZpbmFsVXNlciA/PyAnJykuc3BsaXQoJzonKVswXTtcbiAgaWYgKCFmaW5hbFVzZXIpIGVycignRG9ja2VyZmlsZTogdGhlIGZpbmFsIHN0YWdlIHNldHMgbm8gVVNFUiAoZW5kIHdpdGggYFVTRVIgMTAwMDoxMDAwYCknKTtcbiAgZWxzZSBpZiAodXNlclBhcnQgPT09ICdyb290JyB8fCB1c2VyUGFydCA9PT0gJzAnKSBlcnIoYERvY2tlcmZpbGU6IHRoZSBmaW5hbCBzdGFnZSBydW5zIGFzIHJvb3QgKFVTRVIgJHtmaW5hbFVzZXJ9KTsgZW5kIHdpdGggXFxgVVNFUiAxMDAwOjEwMDBcXGBgKTtcbiAgY29uc3QgcGlwZXMgPSBwaXBlSW5zdGFsbGVycyhjb250ZW50KTtcbiAgaWYgKHBpcGVzLmxlbmd0aCkgZXJyKGBEb2NrZXJmaWxlOiBwaXBlcyBhIGRvd25sb2FkIGludG8gYSBzaGVsbCAodXNlIGEgcGlubmVkIHJlbGVhc2UgdmlhIGZldGNoLXZlcmlmaWVkLCBhIGZldGNoLWFwdC1rZXkgYXB0IHJlcG8sIG9yIGFuIGVjb3N5c3RlbSBiYXNlKTogJHtwaXBlc1swXSEuc2xpY2UoMCwgMTYwKX1gKTtcbiAgY29uc3QgZG93bmxvYWRzID0gcmF3RG93bmxvYWRzKGNvbnRlbnQpO1xuICBpZiAoZG93bmxvYWRzLmxlbmd0aCkgZXJyKGBEb2NrZXJmaWxlOiByYXcgZG93bmxvYWQgbm90IHZpYSBmZXRjaC12ZXJpZmllZDogJHtkb3dubG9hZHNbMF0hLnNsaWNlKDAsIDE2MCl9YCk7XG4gIGlmICgvYXB0LWdldCBpbnN0YWxsLy50ZXN0KGNvbnRlbnQpICYmICEvcm0gLXJmIFxcL3ZhclxcL2xpYlxcL2FwdFxcL2xpc3RzLy50ZXN0KGNvbnRlbnQpKSB7XG4gICAgZXJyKCdEb2NrZXJmaWxlOiBtaXNzaW5nIGFwdCBjYWNoZSBjbGVhbnVwIChybSAtcmYgL3Zhci9saWIvYXB0L2xpc3RzLyopJyk7XG4gIH1cbiAgcmV0dXJuIGZpbmRpbmdzO1xufVxuXG4vKiogTGludCB0aGUgc3BlYyBkb2N1bWVudCAoYXMgcGFyc2VkKSB0aGUgd2F5IHRlc3QtcGx1Z2lucy5zaCBkb2VzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxpbnRQbHVnaW5TcGVjKHNwZWM6IFJlY29yZDxzdHJpbmcsIHVua25vd24+LCBzcGVjVGV4dDogc3RyaW5nKTogUGx1Z2luTGludEZpbmRpbmdbXSB7XG4gIGNvbnN0IGZpbmRpbmdzOiBQbHVnaW5MaW50RmluZGluZ1tdID0gW107XG4gIGNvbnN0IGVyciA9IChtZXNzYWdlOiBzdHJpbmcpID0+IGZpbmRpbmdzLnB1c2goeyBsZXZlbDogJ2Vycm9yJywgbWVzc2FnZSB9KTtcbiAgZm9yIChjb25zdCBmIG9mIFBMVUdJTl9MSU5UX1JFUVVJUkVEX0ZJRUxEUykgaWYgKCEoZiBpbiBzcGVjKSkgZXJyKGBwbHVnaW4tc3BlYy55YW1sOiBtaXNzaW5nIHJlcXVpcmVkIGZpZWxkOiAke2Z9YCk7XG4gIGlmIChzcGVjLnBsdWdpblR5cGUgPT09ICdDb2RlQnVpbGRTdGVwJyB8fCBzcGVjLnBsdWdpblR5cGUgPT09IHVuZGVmaW5lZCkge1xuICAgIGZvciAoY29uc3QgZiBvZiBQTFVHSU5fTElOVF9DT0RFQlVJTERfRklFTERTKSBpZiAoIShmIGluIHNwZWMpKSBlcnIoYHBsdWdpbi1zcGVjLnlhbWw6IG1pc3NpbmcgQ29kZUJ1aWxkIGZpZWxkOiAke2Z9YCk7XG4gIH1cbiAgaWYgKHR5cGVvZiBzcGVjLnZlcnNpb24gPT09ICdzdHJpbmcnICYmICEvXlxcZCtcXC5cXGQrXFwuXFxkKyQvLnRlc3Qoc3BlYy52ZXJzaW9uKSkge1xuICAgIGVycihgcGx1Z2luLXNwZWMueWFtbDogY2F0YWxvZyB2ZXJzaW9ucyBhcmUgcGxhaW4gc2VtdmVyIHgueS56IChnb3QgJHtzcGVjLnZlcnNpb259KWApO1xuICB9XG4gIGlmICh0eXBlb2Ygc3BlYy5kZXNjcmlwdGlvbiAhPT0gJ3N0cmluZycgfHwgc3BlYy5kZXNjcmlwdGlvbi50cmltKCkgPT09ICcnKSBlcnIoJ3BsdWdpbi1zcGVjLnlhbWw6IGVtcHR5IGRlc2NyaXB0aW9uJyk7XG4gIGlmICgna2V5d29yZHMnIGluIHNwZWMgJiYgKCFBcnJheS5pc0FycmF5KHNwZWMua2V5d29yZHMpIHx8IHNwZWMua2V5d29yZHMubGVuZ3RoID09PSAwKSkgZXJyKCdwbHVnaW4tc3BlYy55YW1sOiBlbXB0eSBrZXl3b3JkcyBsaXN0Jyk7XG4gIGNvbnN0IGRvd25sb2FkID0gLyhjdXJsfHdnZXQpXFxzLipodHRwcz86XFwvXFwvW15cXHNcIl0qKHJlbGVhc2VzXFwvZG93bmxvYWRcXC98XFwudGFyXFwuZ3p8XFwudGd6fFxcLnRhclxcLnh6fFxcLnppcCkvLmV4ZWMoc3BlY1RleHQpO1xuICBpZiAoZG93bmxvYWQpIGVycihgcGx1Z2luLXNwZWMueWFtbDogZG93bmxvYWRzIGEgdG9vbCBhdCBydW50aW1lIChiYWtlIGl0IGludG8gdGhlIGltYWdlIHZpYSBmZXRjaC12ZXJpZmllZCk6ICR7ZG93bmxvYWRbMF0uc2xpY2UoMCwgMTYwKX1gKTtcbiAgaWYgKC9eXFxzKi0gXFx8L20udGVzdChzcGVjVGV4dCkgJiYgIS9zZXQgLWUvLnRlc3Qoc3BlY1RleHQpKSB7XG4gICAgZmluZGluZ3MucHVzaCh7IGxldmVsOiAnd2FybmluZycsIG1lc3NhZ2U6ICdwbHVnaW4tc3BlYy55YW1sOiBtdWx0aS1saW5lIGNvbW1hbmQocykgd2l0aG91dCBgc2V0IC1lYCDigJQgaW50ZXJtZWRpYXRlIGZhaWx1cmVzIHdpbGwgc2lsZW50bHkgcGFzcycgfSk7XG4gIH1cbiAgcmV0dXJuIGZpbmRpbmdzO1xufVxuIl19
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/** The comparison form of a plugin name. */
|
|
2
|
+
export declare function normalizeConfusableName(name: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Optimal-string-alignment Damerau–Levenshtein distance between `a` and `b`,
|
|
5
|
+
* giving up (returning `limit + 1`) once it must exceed `limit`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function damerauLevenshtein(a: string, b: string, limit?: number): number;
|
|
8
|
+
/**
|
|
9
|
+
* The first of `names` that `candidate` is confusable with (see the module
|
|
10
|
+
* note), or null. An EXACT match counts too — the caller decides whether the
|
|
11
|
+
* same name is a conflict or the same listing.
|
|
12
|
+
*/
|
|
13
|
+
export declare function findConfusableName(candidate: string, names: Iterable<string>): string | null;
|
|
14
|
+
/** Whether `candidate` is confusable with any of `names`. */
|
|
15
|
+
export declare function isConfusableName(candidate: string, names: Iterable<string>): boolean;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright 2026 Pipeline Builder Contributors
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
/**
|
|
4
|
+
* Confusable plugin names (docs/plugin-publishing.md):
|
|
5
|
+
* a new community listing — an anonymous submission or a `new_listing`
|
|
6
|
+
* request — may not look like one of the directory's most-installed plugins
|
|
7
|
+
* (`terraf0rm`, `kube-ctl`, `docker_build`, `tfsec` → `tfsed`).
|
|
8
|
+
*
|
|
9
|
+
* Two names are CONFUSABLE when, after {@link normalizeConfusableName}
|
|
10
|
+
* (lowercase; strip `-`, `_`, `.`; `rn`→`m`, `vv`→`w`, `0`→`o`, `1`→`l`,
|
|
11
|
+
* `3`→`e`, `5`→`s`), they are equal or one Damerau–Levenshtein edit apart
|
|
12
|
+
* (an insertion, deletion, substitution or adjacent transposition).
|
|
13
|
+
*
|
|
14
|
+
* Pure, so the CLI can warn before a publish and the plugin service decides
|
|
15
|
+
* with the same rule.
|
|
16
|
+
*/
|
|
17
|
+
const MULTI_CHAR = [[/rn/g, 'm'], [/vv/g, 'w']];
|
|
18
|
+
const SINGLE_CHAR = { 0: 'o', 1: 'l', 3: 'e', 5: 's' };
|
|
19
|
+
/** The comparison form of a plugin name. */
|
|
20
|
+
export function normalizeConfusableName(name) {
|
|
21
|
+
let out = name.toLowerCase().replace(/[-_.]/g, '');
|
|
22
|
+
for (const [from, to] of MULTI_CHAR)
|
|
23
|
+
out = out.replace(from, to);
|
|
24
|
+
return out.replace(/[0135]/g, (c) => SINGLE_CHAR[c] ?? c);
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Optimal-string-alignment Damerau–Levenshtein distance between `a` and `b`,
|
|
28
|
+
* giving up (returning `limit + 1`) once it must exceed `limit`.
|
|
29
|
+
*/
|
|
30
|
+
export function damerauLevenshtein(a, b, limit = Number.POSITIVE_INFINITY) {
|
|
31
|
+
if (a === b)
|
|
32
|
+
return 0;
|
|
33
|
+
if (Math.abs(a.length - b.length) > limit)
|
|
34
|
+
return limit + 1;
|
|
35
|
+
if (a.length === 0)
|
|
36
|
+
return b.length;
|
|
37
|
+
if (b.length === 0)
|
|
38
|
+
return a.length;
|
|
39
|
+
let prevPrev = [];
|
|
40
|
+
let prev = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
41
|
+
for (let i = 1; i <= a.length; i++) {
|
|
42
|
+
const cur = [i];
|
|
43
|
+
let rowMin = i;
|
|
44
|
+
for (let j = 1; j <= b.length; j++) {
|
|
45
|
+
const cost = a[i - 1] === b[j - 1] ? 0 : 1;
|
|
46
|
+
let d = Math.min(prev[j] + 1, cur[j - 1] + 1, prev[j - 1] + cost);
|
|
47
|
+
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1])
|
|
48
|
+
d = Math.min(d, prevPrev[j - 2] + 1);
|
|
49
|
+
cur.push(d);
|
|
50
|
+
rowMin = Math.min(rowMin, d);
|
|
51
|
+
}
|
|
52
|
+
if (rowMin > limit)
|
|
53
|
+
return limit + 1;
|
|
54
|
+
prevPrev = prev;
|
|
55
|
+
prev = cur;
|
|
56
|
+
}
|
|
57
|
+
return prev[b.length];
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* The first of `names` that `candidate` is confusable with (see the module
|
|
61
|
+
* note), or null. An EXACT match counts too — the caller decides whether the
|
|
62
|
+
* same name is a conflict or the same listing.
|
|
63
|
+
*/
|
|
64
|
+
export function findConfusableName(candidate, names) {
|
|
65
|
+
const c = normalizeConfusableName(candidate);
|
|
66
|
+
if (c.length === 0)
|
|
67
|
+
return null;
|
|
68
|
+
for (const name of names) {
|
|
69
|
+
const n = normalizeConfusableName(name);
|
|
70
|
+
if (n.length === 0)
|
|
71
|
+
continue;
|
|
72
|
+
if (c === n || damerauLevenshtein(c, n, 1) <= 1)
|
|
73
|
+
return name;
|
|
74
|
+
}
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
/** Whether `candidate` is confusable with any of `names`. */
|
|
78
|
+
export function isConfusableName(candidate, names) {
|
|
79
|
+
return findConfusableName(candidate, names) !== null;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLW5hbWUtY29uZnVzYWJsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy92YWxpZGF0aW9uL3BsdWdpbi1uYW1lLWNvbmZ1c2FibGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0NBQStDO0FBQy9DLHNDQUFzQztBQUV0Qzs7Ozs7Ozs7Ozs7OztHQWFHO0FBRUgsTUFBTSxVQUFVLEdBQW9DLENBQUMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQztBQUNqRixNQUFNLFdBQVcsR0FBcUMsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsRUFBRSxHQUFHLEVBQUUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFFekYsNENBQTRDO0FBQzVDLE1BQU0sVUFBVSx1QkFBdUIsQ0FBQyxJQUFZO0lBQ2xELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQyxPQUFPLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ25ELEtBQUssTUFBTSxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsSUFBSSxVQUFVO1FBQUUsR0FBRyxHQUFHLEdBQUcsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDO0lBQ2pFLE9BQU8sR0FBRyxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztBQUM1RCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLENBQVMsRUFBRSxDQUFTLEVBQUUsS0FBSyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUI7SUFDdkYsSUFBSSxDQUFDLEtBQUssQ0FBQztRQUFFLE9BQU8sQ0FBQyxDQUFDO0lBQ3RCLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsR0FBRyxLQUFLO1FBQUUsT0FBTyxLQUFLLEdBQUcsQ0FBQyxDQUFDO0lBQzVELElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3BDLElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQ3BDLElBQUksUUFBUSxHQUFhLEVBQUUsQ0FBQztJQUM1QixJQUFJLElBQUksR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUM3RCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ25DLE1BQU0sR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDaEIsSUFBSSxNQUFNLEdBQUcsQ0FBQyxDQUFDO1FBQ2YsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNuQyxNQUFNLElBQUksR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzNDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBRSxHQUFHLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBRSxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBRSxHQUFHLElBQUksQ0FBQyxDQUFDO1lBQ3JFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDO2dCQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBRSxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQzVHLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDWixNQUFNLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDL0IsQ0FBQztRQUNELElBQUksTUFBTSxHQUFHLEtBQUs7WUFBRSxPQUFPLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDckMsUUFBUSxHQUFHLElBQUksQ0FBQztRQUNoQixJQUFJLEdBQUcsR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUUsQ0FBQztBQUN6QixDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxTQUFpQixFQUFFLEtBQXVCO0lBQzNFLE1BQU0sQ0FBQyxHQUFHLHVCQUF1QixDQUFDLFNBQVMsQ0FBQyxDQUFDO0lBQzdDLElBQUksQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDaEMsS0FBSyxNQUFNLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN6QixNQUFNLENBQUMsR0FBRyx1QkFBdUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUN4QyxJQUFJLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQztZQUFFLFNBQVM7UUFDN0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLGtCQUFrQixDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQztZQUFFLE9BQU8sSUFBSSxDQUFDO0lBQy9ELENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCw2REFBNkQ7QUFDN0QsTUFBTSxVQUFVLGdCQUFnQixDQUFDLFNBQWlCLEVBQUUsS0FBdUI7SUFDekUsT0FBTyxrQkFBa0IsQ0FBQyxTQUFTLEVBQUUsS0FBSyxDQUFDLEtBQUssSUFBSSxDQUFDO0FBQ3ZELENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBDb3B5cmlnaHQgMjAyNiBQaXBlbGluZSBCdWlsZGVyIENvbnRyaWJ1dG9yc1xuLy8gU1BEWC1MaWNlbnNlLUlkZW50aWZpZXI6IEFwYWNoZS0yLjBcblxuLyoqXG4gKiBDb25mdXNhYmxlIHBsdWdpbiBuYW1lcyAoZG9jcy9wbHVnaW4tcHVibGlzaGluZy5tZCk6XG4gKiBhIG5ldyBjb21tdW5pdHkgbGlzdGluZyDigJQgYW4gYW5vbnltb3VzIHN1Ym1pc3Npb24gb3IgYSBgbmV3X2xpc3RpbmdgXG4gKiByZXF1ZXN0IOKAlCBtYXkgbm90IGxvb2sgbGlrZSBvbmUgb2YgdGhlIGRpcmVjdG9yeSdzIG1vc3QtaW5zdGFsbGVkIHBsdWdpbnNcbiAqIChgdGVycmFmMHJtYCwgYGt1YmUtY3RsYCwgYGRvY2tlcl9idWlsZGAsIGB0ZnNlY2Ag4oaSIGB0ZnNlZGApLlxuICpcbiAqIFR3byBuYW1lcyBhcmUgQ09ORlVTQUJMRSB3aGVuLCBhZnRlciB7QGxpbmsgbm9ybWFsaXplQ29uZnVzYWJsZU5hbWV9XG4gKiAobG93ZXJjYXNlOyBzdHJpcCBgLWAsIGBfYCwgYC5gOyBgcm5g4oaSYG1gLCBgdnZg4oaSYHdgLCBgMGDihpJgb2AsIGAxYOKGkmBsYCxcbiAqIGAzYOKGkmBlYCwgYDVg4oaSYHNgKSwgdGhleSBhcmUgZXF1YWwgb3Igb25lIERhbWVyYXXigJNMZXZlbnNodGVpbiBlZGl0IGFwYXJ0XG4gKiAoYW4gaW5zZXJ0aW9uLCBkZWxldGlvbiwgc3Vic3RpdHV0aW9uIG9yIGFkamFjZW50IHRyYW5zcG9zaXRpb24pLlxuICpcbiAqIFB1cmUsIHNvIHRoZSBDTEkgY2FuIHdhcm4gYmVmb3JlIGEgcHVibGlzaCBhbmQgdGhlIHBsdWdpbiBzZXJ2aWNlIGRlY2lkZXNcbiAqIHdpdGggdGhlIHNhbWUgcnVsZS5cbiAqL1xuXG5jb25zdCBNVUxUSV9DSEFSOiBSZWFkb25seUFycmF5PFtSZWdFeHAsIHN0cmluZ10+ID0gW1svcm4vZywgJ20nXSwgWy92di9nLCAndyddXTtcbmNvbnN0IFNJTkdMRV9DSEFSOiBSZWFkb25seTxSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+PiA9IHsgMDogJ28nLCAxOiAnbCcsIDM6ICdlJywgNTogJ3MnIH07XG5cbi8qKiBUaGUgY29tcGFyaXNvbiBmb3JtIG9mIGEgcGx1Z2luIG5hbWUuICovXG5leHBvcnQgZnVuY3Rpb24gbm9ybWFsaXplQ29uZnVzYWJsZU5hbWUobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgbGV0IG91dCA9IG5hbWUudG9Mb3dlckNhc2UoKS5yZXBsYWNlKC9bLV8uXS9nLCAnJyk7XG4gIGZvciAoY29uc3QgW2Zyb20sIHRvXSBvZiBNVUxUSV9DSEFSKSBvdXQgPSBvdXQucmVwbGFjZShmcm9tLCB0byk7XG4gIHJldHVybiBvdXQucmVwbGFjZSgvWzAxMzVdL2csIChjKSA9PiBTSU5HTEVfQ0hBUltjXSA/PyBjKTtcbn1cblxuLyoqXG4gKiBPcHRpbWFsLXN0cmluZy1hbGlnbm1lbnQgRGFtZXJhdeKAk0xldmVuc2h0ZWluIGRpc3RhbmNlIGJldHdlZW4gYGFgIGFuZCBgYmAsXG4gKiBnaXZpbmcgdXAgKHJldHVybmluZyBgbGltaXQgKyAxYCkgb25jZSBpdCBtdXN0IGV4Y2VlZCBgbGltaXRgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGFtZXJhdUxldmVuc2h0ZWluKGE6IHN0cmluZywgYjogc3RyaW5nLCBsaW1pdCA9IE51bWJlci5QT1NJVElWRV9JTkZJTklUWSk6IG51bWJlciB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gMDtcbiAgaWYgKE1hdGguYWJzKGEubGVuZ3RoIC0gYi5sZW5ndGgpID4gbGltaXQpIHJldHVybiBsaW1pdCArIDE7XG4gIGlmIChhLmxlbmd0aCA9PT0gMCkgcmV0dXJuIGIubGVuZ3RoO1xuICBpZiAoYi5sZW5ndGggPT09IDApIHJldHVybiBhLmxlbmd0aDtcbiAgbGV0IHByZXZQcmV2OiBudW1iZXJbXSA9IFtdO1xuICBsZXQgcHJldiA9IEFycmF5LmZyb20oeyBsZW5ndGg6IGIubGVuZ3RoICsgMSB9LCAoXywgaikgPT4gaik7XG4gIGZvciAobGV0IGkgPSAxOyBpIDw9IGEubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCBjdXIgPSBbaV07XG4gICAgbGV0IHJvd01pbiA9IGk7XG4gICAgZm9yIChsZXQgaiA9IDE7IGogPD0gYi5sZW5ndGg7IGorKykge1xuICAgICAgY29uc3QgY29zdCA9IGFbaSAtIDFdID09PSBiW2ogLSAxXSA/IDAgOiAxO1xuICAgICAgbGV0IGQgPSBNYXRoLm1pbihwcmV2W2pdISArIDEsIGN1cltqIC0gMV0hICsgMSwgcHJldltqIC0gMV0hICsgY29zdCk7XG4gICAgICBpZiAoaSA+IDEgJiYgaiA+IDEgJiYgYVtpIC0gMV0gPT09IGJbaiAtIDJdICYmIGFbaSAtIDJdID09PSBiW2ogLSAxXSkgZCA9IE1hdGgubWluKGQsIHByZXZQcmV2W2ogLSAyXSEgKyAxKTtcbiAgICAgIGN1ci5wdXNoKGQpO1xuICAgICAgcm93TWluID0gTWF0aC5taW4ocm93TWluLCBkKTtcbiAgICB9XG4gICAgaWYgKHJvd01pbiA+IGxpbWl0KSByZXR1cm4gbGltaXQgKyAxO1xuICAgIHByZXZQcmV2ID0gcHJldjtcbiAgICBwcmV2ID0gY3VyO1xuICB9XG4gIHJldHVybiBwcmV2W2IubGVuZ3RoXSE7XG59XG5cbi8qKlxuICogVGhlIGZpcnN0IG9mIGBuYW1lc2AgdGhhdCBgY2FuZGlkYXRlYCBpcyBjb25mdXNhYmxlIHdpdGggKHNlZSB0aGUgbW9kdWxlXG4gKiBub3RlKSwgb3IgbnVsbC4gQW4gRVhBQ1QgbWF0Y2ggY291bnRzIHRvbyDigJQgdGhlIGNhbGxlciBkZWNpZGVzIHdoZXRoZXIgdGhlXG4gKiBzYW1lIG5hbWUgaXMgYSBjb25mbGljdCBvciB0aGUgc2FtZSBsaXN0aW5nLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZmluZENvbmZ1c2FibGVOYW1lKGNhbmRpZGF0ZTogc3RyaW5nLCBuYW1lczogSXRlcmFibGU8c3RyaW5nPik6IHN0cmluZyB8IG51bGwge1xuICBjb25zdCBjID0gbm9ybWFsaXplQ29uZnVzYWJsZU5hbWUoY2FuZGlkYXRlKTtcbiAgaWYgKGMubGVuZ3RoID09PSAwKSByZXR1cm4gbnVsbDtcbiAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgY29uc3QgbiA9IG5vcm1hbGl6ZUNvbmZ1c2FibGVOYW1lKG5hbWUpO1xuICAgIGlmIChuLmxlbmd0aCA9PT0gMCkgY29udGludWU7XG4gICAgaWYgKGMgPT09IG4gfHwgZGFtZXJhdUxldmVuc2h0ZWluKGMsIG4sIDEpIDw9IDEpIHJldHVybiBuYW1lO1xuICB9XG4gIHJldHVybiBudWxsO1xufVxuXG4vKiogV2hldGhlciBgY2FuZGlkYXRlYCBpcyBjb25mdXNhYmxlIHdpdGggYW55IG9mIGBuYW1lc2AuICovXG5leHBvcnQgZnVuY3Rpb24gaXNDb25mdXNhYmxlTmFtZShjYW5kaWRhdGU6IHN0cmluZywgbmFtZXM6IEl0ZXJhYmxlPHN0cmluZz4pOiBib29sZWFuIHtcbiAgcmV0dXJuIGZpbmRDb25mdXNhYmxlTmFtZShjYW5kaWRhdGUsIG5hbWVzKSAhPT0gbnVsbDtcbn1cbiJdfQ==
|
|
@@ -24,6 +24,7 @@ export declare const PluginFilterSchema: z.ZodObject<{
|
|
|
24
24
|
production: "production";
|
|
25
25
|
}>>;
|
|
26
26
|
name: z.ZodOptional<z.ZodString>;
|
|
27
|
+
publisher: z.ZodOptional<z.ZodString>;
|
|
27
28
|
version: z.ZodOptional<z.ZodString>;
|
|
28
29
|
orgId: z.ZodOptional<z.ZodString>;
|
|
29
30
|
pluginType: z.ZodOptional<z.ZodString>;
|
|
@@ -96,7 +97,13 @@ export declare const PluginCreateSchema: z.ZodObject<{
|
|
|
96
97
|
}, z.core.$strip>>>;
|
|
97
98
|
}, z.core.$strip>;
|
|
98
99
|
/**
|
|
99
|
-
* Plugin update schema
|
|
100
|
+
* Plugin update schema (`PUT /plugins/:id`).
|
|
101
|
+
*
|
|
102
|
+
* DESCRIPTIVE catalog fields only plus the version's operational
|
|
103
|
+
* flags and developer-portal metadata. Execution-contract keys (commands, env,
|
|
104
|
+
* secrets, compute type, …) are never accepted — the route refuses them with a
|
|
105
|
+
* 400 naming the keys before this schema runs, and `.strict()` refuses anything
|
|
106
|
+
* else unknown rather than silently dropping it.
|
|
100
107
|
*/
|
|
101
108
|
export declare const PluginUpdateSchema: z.ZodObject<{
|
|
102
109
|
ownerId: z.ZodOptional<z.ZodString>;
|
|
@@ -121,19 +128,6 @@ export declare const PluginUpdateSchema: z.ZodObject<{
|
|
|
121
128
|
url: z.ZodString;
|
|
122
129
|
icon: z.ZodOptional<z.ZodString>;
|
|
123
130
|
}, z.core.$strip>>>;
|
|
124
|
-
name: z.ZodOptional<z.ZodString>;
|
|
125
|
-
description: z.ZodOptional<z.ZodString>;
|
|
126
|
-
keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
127
|
-
category: z.ZodOptional<z.ZodString>;
|
|
128
|
-
version: z.ZodOptional<z.ZodString>;
|
|
129
|
-
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
130
|
-
pluginType: z.ZodOptional<z.ZodString>;
|
|
131
|
-
computeType: z.ZodOptional<z.ZodString>;
|
|
132
|
-
primaryOutputDirectory: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
133
|
-
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
134
|
-
buildArgs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
135
|
-
installCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
136
|
-
commands: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
137
131
|
isActive: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodPipe<z.ZodEnum<{
|
|
138
132
|
false: "false";
|
|
139
133
|
true: "true";
|
|
@@ -147,18 +141,33 @@ export declare const PluginUpdateSchema: z.ZodObject<{
|
|
|
147
141
|
private: "private";
|
|
148
142
|
public: "public";
|
|
149
143
|
}>>;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
}
|
|
144
|
+
category: z.ZodOptional<z.ZodNullable<z.ZodEnum<{
|
|
145
|
+
ai: "ai";
|
|
146
|
+
artifact: "artifact";
|
|
147
|
+
deploy: "deploy";
|
|
148
|
+
infrastructure: "infrastructure";
|
|
149
|
+
language: "language";
|
|
150
|
+
monitoring: "monitoring";
|
|
151
|
+
notification: "notification";
|
|
152
|
+
quality: "quality";
|
|
153
|
+
security: "security";
|
|
154
|
+
testing: "testing";
|
|
155
|
+
}>>>;
|
|
156
|
+
changelog: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
157
|
+
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
158
|
+
displayName: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
159
|
+
documentationUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
160
|
+
homepageUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
161
|
+
icon: z.ZodOptional<z.ZodNullable<z.ZodPreprocess<z.ZodObject<{
|
|
162
|
+
key: z.ZodString;
|
|
163
|
+
badge: z.ZodOptional<z.ZodString>;
|
|
164
|
+
}, z.core.$strict>>>>;
|
|
165
|
+
keywords: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
166
|
+
license: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
167
|
+
readme: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
168
|
+
sourceUrl: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
169
|
+
summary: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
170
|
+
}, z.core.$strict>;
|
|
162
171
|
/**
|
|
163
172
|
* Plugin upload body schema (multipart form-data text fields)
|
|
164
173
|
*/
|
|
@@ -168,4 +177,9 @@ export declare const PluginUploadBodySchema: z.ZodObject<{
|
|
|
168
177
|
private: "private";
|
|
169
178
|
public: "public";
|
|
170
179
|
}>>;
|
|
180
|
+
metadata: z.ZodOptional<z.ZodString>;
|
|
181
|
+
publishRequest: z.ZodOptional<z.ZodEnum<{
|
|
182
|
+
false: "false";
|
|
183
|
+
true: "true";
|
|
184
|
+
}>>;
|
|
171
185
|
}, z.core.$strip>;
|
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
// SPDX-License-Identifier: Apache-2.0
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
import { BaseFilterSchema, BooleanQuerySchema, VisibilitySchema, CatalogMetadataShape } from './common-schemas.js';
|
|
5
|
+
import { PluginCatalogEditsSchema } from './plugin-catalog-metadata.js';
|
|
6
|
+
import { PUBLISHER_HANDLE_PATTERN } from '../types/ecosystem.js';
|
|
5
7
|
/**
|
|
6
8
|
* Plugin filter schema for query parameters
|
|
7
9
|
*/
|
|
8
10
|
export const PluginFilterSchema = BaseFilterSchema.extend({
|
|
9
11
|
name: z.string().min(1).optional(),
|
|
12
|
+
/** Resolve through this publisher's installed listing; lookup only. */
|
|
13
|
+
publisher: z.string().max(39).regex(PUBLISHER_HANDLE_PATTERN).optional(),
|
|
10
14
|
version: z.string().min(1).optional(),
|
|
11
15
|
orgId: z.string().min(1).optional(),
|
|
12
16
|
pluginType: z.string().optional(),
|
|
@@ -44,38 +48,37 @@ export const PluginCreateSchema = z.object({
|
|
|
44
48
|
})).optional(),
|
|
45
49
|
});
|
|
46
50
|
/**
|
|
47
|
-
* Plugin update schema
|
|
51
|
+
* Plugin update schema (`PUT /plugins/:id`).
|
|
52
|
+
*
|
|
53
|
+
* DESCRIPTIVE catalog fields only plus the version's operational
|
|
54
|
+
* flags and developer-portal metadata. Execution-contract keys (commands, env,
|
|
55
|
+
* secrets, compute type, …) are never accepted — the route refuses them with a
|
|
56
|
+
* 400 naming the keys before this schema runs, and `.strict()` refuses anything
|
|
57
|
+
* else unknown rather than silently dropping it.
|
|
48
58
|
*/
|
|
49
59
|
export const PluginUpdateSchema = z.object({
|
|
50
60
|
...CatalogMetadataShape,
|
|
51
|
-
|
|
52
|
-
description: z.string().optional(),
|
|
53
|
-
keywords: z.array(z.string()).optional(),
|
|
54
|
-
category: z.string().min(1).optional(),
|
|
55
|
-
version: z.string().min(1).optional(),
|
|
56
|
-
metadata: z.record(z.string(), z.unknown()).optional(),
|
|
57
|
-
pluginType: z.string().optional(),
|
|
58
|
-
computeType: z.string().optional(),
|
|
59
|
-
primaryOutputDirectory: z.string().nullable().optional(),
|
|
60
|
-
env: z.record(z.string(), z.string()).optional(),
|
|
61
|
-
buildArgs: z.record(z.string(), z.string()).optional(),
|
|
62
|
-
installCommands: z.array(z.string()).optional(),
|
|
63
|
-
commands: z.array(z.string()).optional(),
|
|
61
|
+
...PluginCatalogEditsSchema.shape,
|
|
64
62
|
isActive: BooleanQuerySchema.optional(),
|
|
65
63
|
isDefault: BooleanQuerySchema.optional(),
|
|
66
64
|
visibility: VisibilitySchema.optional(),
|
|
67
|
-
|
|
68
|
-
failureBehavior: z.enum(['fail', 'warn', 'ignore']).optional(),
|
|
69
|
-
secrets: z.array(z.object({
|
|
70
|
-
name: z.string().min(1),
|
|
71
|
-
required: z.boolean(),
|
|
72
|
-
description: z.string().optional(),
|
|
73
|
-
})).optional(),
|
|
74
|
-
});
|
|
65
|
+
}).strict();
|
|
75
66
|
/**
|
|
76
67
|
* Plugin upload body schema (multipart form-data text fields)
|
|
77
68
|
*/
|
|
78
69
|
export const PluginUploadBodySchema = z.object({
|
|
79
70
|
visibility: VisibilitySchema.optional(),
|
|
71
|
+
/**
|
|
72
|
+
* Catalog metadata edits as a JSON object (a {@link PluginCatalogEditsSchema}
|
|
73
|
+
* document). Absent ⇒ every value detected from the package is accepted.
|
|
74
|
+
*/
|
|
75
|
+
metadata: z.string().max(256 * 1024).optional(),
|
|
76
|
+
/**
|
|
77
|
+
* `true`: once the build completes, submit a publish request (new listing, or
|
|
78
|
+
* new version of the org's existing listing) for the built version as the
|
|
79
|
+
* uploader (docs/plugin-publishing.md). Needs `plugins:publish` and
|
|
80
|
+
* `visibility=public`. The Official catalog loader always sets it.
|
|
81
|
+
*/
|
|
82
|
+
publishRequest: z.enum(['true', 'false']).optional(),
|
|
80
83
|
});
|
|
81
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
84
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGx1Z2luLXNjaGVtYXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdmFsaWRhdGlvbi9wbHVnaW4tc2NoZW1hcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSwrQ0FBK0M7QUFDL0Msc0NBQXNDO0FBRXRDLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxLQUFLLENBQUM7QUFDeEIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLG9CQUFvQixFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFDbkgsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDeEUsT0FBTyxFQUFFLHdCQUF3QixFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFakU7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUM7SUFDeEQsSUFBSSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFO0lBQ2xDLHVFQUF1RTtJQUN2RSxTQUFTLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxRQUFRLEVBQUU7SUFDeEUsT0FBTyxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFO0lBQ3JDLEtBQUssRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRTtJQUNuQyxVQUFVLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNqQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFR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RUFBRTtJQUN2QyxTQUFTLEVBQUUsa0JBQWtCLENBQUMsUUFBUSxFQUFFO0lBQ3hDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUU7Q0FDeEMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDO0FBRVo7O0dBRUc7QUFDSCxNQUFNLENBQUMsTUFBTSxzQkFBc0IsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzdDLFVBQVUsRUFBRSxnQkFBZ0IsQ0FBQyxRQUFRLEVBQUU7SUFDdkM7OztPQUdHO0lBQ0gsUUFBUSxFQUFFLENBQUMsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLENBQUMsR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLFFBQVEsRUFBRTtJQUMvQzs7Ozs7T0FLRztJQUNILGNBQWMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFO0NBQ3JELENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8vIENvcHlyaWdodCAyMDI2IFBpcGVsaW5lIEJ1aWxkZXIgQ29udHJpYnV0b3JzXG4vLyBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogQXBhY2hlLTIuMFxuXG5pbXBvcnQgeyB6IH0gZnJvbSAnem9kJztcbmltcG9ydCB7IEJhc2VGaWx0ZXJTY2hlbWEsIEJvb2xlYW5RdWVyeVNjaGVtYSwgVmlzaWJpbGl0eVNjaGVtYSwgQ2F0YWxvZ01ldGFkYXRhU2hhcGUgfSBmcm9tICcuL2NvbW1vbi1zY2hlbWFzLmpzJztcbmltcG9ydCB7IFBsdWdpbkNhdGFsb2dFZGl0c1NjaGVtYSB9IGZyb20gJy4vcGx1Z2luLWNhdGFsb2ctbWV0YWRhdGEuanMnO1xuaW1wb3J0IHsgUFVCTElTSEVSX0hBTkRMRV9QQVRURVJOIH0gZnJvbSAnLi4vdHlwZXMvZWNvc3lzdGVtLmpzJztcblxuLyoqXG4gKiBQbHVnaW4gZmlsdGVyIHNjaGVtYSBmb3IgcXVlcnkgcGFyYW1ldGVyc1xuICovXG5leHBvcnQgY29uc3QgUGx1Z2luRmlsdGVyU2NoZW1hID0gQmFzZUZpbHRlclNjaGVtYS5leHRlbmQoe1xuICBuYW1lOiB6LnN0cmluZygpLm1pbigxKS5vcHRpb25hbCgpLFxuICAvKiogUmVzb2x2ZSB0aHJvdWdoIHRoaXMgcHVibGlzaGVyJ3MgaW5zdGFsbGVkIGxpc3Rpbmc7IGxvb2t1cCBvbmx5LiAqL1xuICBwdWJsaXNoZXI6IHouc3RyaW5nKCkubWF4KDM5KS5yZWdleChQVUJMSVNIRVJfSEFORExFX1BBVFRFUk4pLm9wdGlvbmFsKCksXG4gIHZlcnNpb246IHouc3RyaW5nKCkubWluKDEpLm9wdGlvbmFsKCksXG4gIG9yZ0lkOiB6LnN0cmluZygpLm1pbigxKS5vcHRpb25hbCgpLFxuICBwbHVnaW5UeXBlOiB6LnN0cmluZygpLm9wdGlvbmFsKCksXG4gIGtleXdvcmQ6IHouc3RyaW5nKCkubWluKDEpLm9wdGlvbmFsKCksXG4gIGNhdGVnb3J5OiB6LnN0cmluZygpLm1pbigxKS5vcHRpb25hbCgpLFxufSk7XG5cbi8qKlxuICogUGx1Z2luIGNyZWF0aW9uIHNjaGVtYSDigJQgdXNlZCBmb3IgT3BlbkFQSSBkb2N1bWVudGF0aW9uIGFuZCBkaXJlY3QgQVBJIGNyZWF0aW9uLlxuICogQ3VycmVudGx5IG5vIHJvdXRlIHVzZXMgdGhpcyBkaXJlY3RseTsgcGx1Z2lucyBhcmUgY3JlYXRlZCB2aWEgdXBsb2FkIG9yIEFJIGdlbmVyYXRpb24uXG4gKiBSZXRhaW5lZCBmb3IgZnV0dXJlIGRpcmVjdC1jcmVhdGUgZW5kcG9pbnQgYW5kIE9wZW5BUEkgc3BlYyBjb21wbGV0ZW5lc3MuXG4gKi9cbmV4cG9ydCBjb25zdCBQbHVnaW5DcmVhdGVTY2hlbWEgPSB6Lm9iamVjdCh7XG4gIC4uLkNhdGFsb2dNZXRhZGF0YVNoYXBlLFxuICBvcmdJZDogei5zdHJpbmcoKS5taW4oMSwgJ09yZ2FuaXphdGlvbiBJRCBpcyByZXF1aXJlZCcpLFxuICBuYW1lOiB6LnN0cmluZygpLm1pbigxLCAnUGx1Z2luIG5hbWUgaXMgcmVxdWlyZWQnKSxcbiAgdmVyc2lvbjogei5zdHJpbmcoKS5taW4oMSwgJ1ZlcnNpb24gaXMgcmVxdWlyZWQnKSxcbiAgdmlzaWJpbGl0eTogVmlzaWJpbGl0eVNjaGVtYS5vcHRpb25hbCgpLFxuICBjYXRlZ29yeTogei5zdHJpbmcoKS5taW4oMSkub3B0aW9uYWwoKSxcbiAgcGx1Z2luVHlwZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICBjb21wdXRlVHlwZTogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICBwcmltYXJ5T3V0cHV0RGlyZWN0b3J5OiB6LnN0cmluZygpLm51bGxhYmxlKCkub3B0aW9uYWwoKSxcbiAgbWV0YWRhdGE6IHoucmVjb3JkKHouc3RyaW5nKCksIHoudW5rbm93bigpKS5vcHRpb25hbCgpLFxuICBlbnY6IHoucmVjb3JkKHouc3RyaW5nKCksIHouc3RyaW5nKCkpLm9wdGlvbmFsKCksXG4gIGJ1aWxkQXJnczogei5yZWNvcmQoei5zdHJpbmcoKSwgei5zdHJpbmcoKSkub3B0aW9uYWwoKSxcbiAgaW5zdGFsbENvbW1hbmRzOiB6LmFycmF5KHouc3RyaW5nKCkpLm9wdGlvbmFsKCksXG4gIGNvbW1hbmRzOiB6LmFycmF5KHouc3RyaW5nKCkpLm9wdGlvbmFsKCksXG4gIGlzQWN0aXZlOiBCb29sZWFuUXVlcnlTY2hlbWEub3B0aW9uYWwoKSxcbiAgaXNEZWZhdWx0OiBCb29sZWFuUXVlcnlTY2hlbWEub3B0aW9uYWwoKSxcbiAgdGltZW91dDogei5udW1iZXIoKS5pbnQoKS5wb3NpdGl2ZSgpLm51bGxhYmxlKCkub3B0aW9uYWwoKSxcbiAgZmFpbHVyZUJlaGF2aW9yOiB6LmVudW0oWydmYWlsJywgJ3dhcm4nLCAnaWdub3JlJ10pLm9wdGlvbmFsKCksXG4gIHNlY3JldHM6IHouYXJyYXkoei5vYmplY3Qoe1xuICAgIG5hbWU6IHouc3RyaW5nKCkubWluKDEpLFxuICAgIHJlcXVpcmVkOiB6LmJvb2xlYW4oKSxcbiAgICBkZXNjcmlwdGlvbjogei5zdHJpbmcoKS5vcHRpb25hbCgpLFxuICB9KSkub3B0aW9uYWwoKSxcbn0pO1xuXG4vKipcbiAqIFBsdWdpbiB1cGRhdGUgc2NoZW1hIChgUFVUIC9wbHVnaW5zLzppZGApLlxuICpcbiAqIERFU0NSSVBUSVZFIGNhdGFsb2cgZmllbGRzIG9ubHkgcGx1cyB0aGUgdmVyc2lvbidzIG9wZXJhdGlvbmFsXG4gKiBmbGFncyBhbmQgZGV2ZWxvcGVyLXBvcnRhbCBtZXRhZGF0YS4gRXhlY3V0aW9uLWNvbnRyYWN0IGtleXMgKGNvbW1hbmRzLCBlbnYsXG4gKiBzZWNyZXRzLCBjb21wdXRlIHR5cGUsIOKApikgYXJlIG5ldmVyIGFjY2VwdGVkIOKAlCB0aGUgcm91dGUgcmVmdXNlcyB0aGVtIHdpdGggYVxuICogNDAwIG5hbWluZyB0aGUga2V5cyBiZWZvcmUgdGhpcyBzY2hlbWEgcnVucywgYW5kIGAuc3RyaWN0KClgIHJlZnVzZXMgYW55dGhpbmdcbiAqIGVsc2UgdW5rbm93biByYXRoZXIgdGhhbiBzaWxlbnRseSBkcm9wcGluZyBpdC5cbiAqL1xuZXhwb3J0IGNvbnN0IFBsdWdpblVwZGF0ZVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgLi4uQ2F0YWxvZ01ldGFkYXRhU2hhcGUsXG4gIC4uLlBsdWdpbkNhdGFsb2dFZGl0c1NjaGVtYS5zaGFwZSxcbiAgaXNBY3RpdmU6IEJvb2xlYW5RdWVyeVNjaGVtYS5vcHRpb25hbCgpLFxuICBpc0RlZmF1bHQ6IEJvb2xlYW5RdWVyeVNjaGVtYS5vcHRpb25hbCgpLFxuICB2aXNpYmlsaXR5OiBWaXNpYmlsaXR5U2NoZW1hLm9wdGlvbmFsKCksXG59KS5zdHJpY3QoKTtcblxuLyoqXG4gKiBQbHVnaW4gdXBsb2FkIGJvZHkgc2NoZW1hIChtdWx0aXBhcnQgZm9ybS1kYXRhIHRleHQgZmllbGRzKVxuICovXG5leHBvcnQgY29uc3QgUGx1Z2luVXBsb2FkQm9keVNjaGVtYSA9IHoub2JqZWN0KHtcbiAgdmlzaWJpbGl0eTogVmlzaWJpbGl0eVNjaGVtYS5vcHRpb25hbCgpLFxuICAvKipcbiAgICogQ2F0YWxvZyBtZXRhZGF0YSBlZGl0cyBhcyBhIEpTT04gb2JqZWN0IChhIHtAbGluayBQbHVnaW5DYXRhbG9nRWRpdHNTY2hlbWF9XG4gICAqIGRvY3VtZW50KS4gQWJzZW50IOKHkiBldmVyeSB2YWx1ZSBkZXRlY3RlZCBmcm9tIHRoZSBwYWNrYWdlIGlzIGFjY2VwdGVkLlxuICAgKi9cbiAgbWV0YWRhdGE6IHouc3RyaW5nKCkubWF4KDI1NiAqIDEwMjQpLm9wdGlvbmFsKCksXG4gIC8qKlxuICAgKiBgdHJ1ZWA6IG9uY2UgdGhlIGJ1aWxkIGNvbXBsZXRlcywgc3VibWl0IGEgcHVibGlzaCByZXF1ZXN0IChuZXcgbGlzdGluZywgb3JcbiAgICogbmV3IHZlcnNpb24gb2YgdGhlIG9yZydzIGV4aXN0aW5nIGxpc3RpbmcpIGZvciB0aGUgYnVpbHQgdmVyc2lvbiBhcyB0aGVcbiAgICogdXBsb2FkZXIgKGRvY3MvcGx1Z2luLXB1Ymxpc2hpbmcubWQpLiBOZWVkcyBgcGx1Z2luczpwdWJsaXNoYCBhbmRcbiAgICogYHZpc2liaWxpdHk9cHVibGljYC4gVGhlIE9mZmljaWFsIGNhdGFsb2cgbG9hZGVyIGFsd2F5cyBzZXRzIGl0LlxuICAgKi9cbiAgcHVibGlzaFJlcXVlc3Q6IHouZW51bShbJ3RydWUnLCAnZmFsc2UnXSkub3B0aW9uYWwoKSxcbn0pO1xuIl19
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The plugin PACKAGE schemas: `plugin-spec.yaml` and `config.yaml`, exactly as
|
|
3
|
+
* the plugin service validates an upload. Shared from api-core so the upload
|
|
4
|
+
* path (api/plugin) and the CLI (`pipeline-manager plugin validate` /
|
|
5
|
+
* `plugin publish`) apply ONE schema and can't drift.
|
|
6
|
+
*
|
|
7
|
+
* Pure: no YAML parsing, no filesystem. Callers parse (with their own size and
|
|
8
|
+
* alias bounds) and hand the resulting object to {@link checkPluginSpec} /
|
|
9
|
+
* {@link checkPluginConfig}.
|
|
10
|
+
*/
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
export declare const PLUGIN_TYPES: readonly ['CodeBuildStep', 'ShellStep', 'ManualApprovalStep'];
|
|
13
|
+
export declare const PLUGIN_COMPUTE_TYPES: readonly ['SMALL', 'MEDIUM', 'LARGE', 'X2_LARGE'];
|
|
14
|
+
export declare const PLUGIN_FAILURE_BEHAVIORS: readonly ['fail', 'warn', 'ignore'];
|
|
15
|
+
export declare const PLUGIN_BUILD_TYPES: readonly ['build_image', 'prebuilt', 'metadata_only'];
|
|
16
|
+
export type PluginBuildType = typeof PLUGIN_BUILD_TYPES[number];
|
|
17
|
+
/** Plugin name: lowercase letters, digits and hyphens. */
|
|
18
|
+
export declare const PLUGIN_NAME_PATTERN: RegExp;
|
|
19
|
+
/** Plugin version: semver, with optional `-prerelease` and `+build` metadata. */
|
|
20
|
+
export declare const PLUGIN_VERSION_PATTERN: RegExp;
|
|
21
|
+
/** Max declared `network.egress` hostnames. */
|
|
22
|
+
export declare const EGRESS_MAX_HOSTS = 50;
|
|
23
|
+
/** True when `host` is an acceptable `network.egress` entry. */
|
|
24
|
+
export declare function isValidEgressHost(host: string): boolean;
|
|
25
|
+
export declare const PluginConfigSchema: z.ZodObject<{
|
|
26
|
+
pluginSpec: z.ZodOptional<z.ZodString>;
|
|
27
|
+
dockerfile: z.ZodOptional<z.ZodString>;
|
|
28
|
+
buildType: z.ZodOptional<z.ZodEnum<{
|
|
29
|
+
build_image: "build_image";
|
|
30
|
+
metadata_only: "metadata_only";
|
|
31
|
+
prebuilt: "prebuilt";
|
|
32
|
+
}>>;
|
|
33
|
+
imageTag: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strict>;
|
|
35
|
+
export type PluginConfigInput = z.infer<typeof PluginConfigSchema>;
|
|
36
|
+
export declare const PluginSpecSchema: z.ZodObject<{
|
|
37
|
+
name: z.ZodOptional<z.ZodString>;
|
|
38
|
+
description: z.ZodOptional<z.ZodString>;
|
|
39
|
+
keywords: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
40
|
+
category: z.ZodOptional<z.ZodString>;
|
|
41
|
+
version: z.ZodOptional<z.ZodString>;
|
|
42
|
+
pluginType: z.ZodOptional<z.ZodEnum<{
|
|
43
|
+
CodeBuildStep: "CodeBuildStep";
|
|
44
|
+
ManualApprovalStep: "ManualApprovalStep";
|
|
45
|
+
ShellStep: "ShellStep";
|
|
46
|
+
}>>;
|
|
47
|
+
computeType: z.ZodOptional<z.ZodEnum<{
|
|
48
|
+
LARGE: "LARGE";
|
|
49
|
+
MEDIUM: "MEDIUM";
|
|
50
|
+
SMALL: "SMALL";
|
|
51
|
+
X2_LARGE: "X2_LARGE";
|
|
52
|
+
}>>;
|
|
53
|
+
timeout: z.ZodOptional<z.ZodNumber>;
|
|
54
|
+
failureBehavior: z.ZodOptional<z.ZodEnum<{
|
|
55
|
+
fail: "fail";
|
|
56
|
+
ignore: "ignore";
|
|
57
|
+
warn: "warn";
|
|
58
|
+
}>>;
|
|
59
|
+
secrets: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
60
|
+
name: z.ZodString;
|
|
61
|
+
required: z.ZodBoolean;
|
|
62
|
+
description: z.ZodOptional<z.ZodString>;
|
|
63
|
+
}, z.core.$strip>>>;
|
|
64
|
+
primaryOutputDirectory: z.ZodPipe<z.ZodOptional<z.ZodNullable<z.ZodString>>, z.ZodTransform<string | undefined, string | null | undefined>>;
|
|
65
|
+
metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>>>;
|
|
66
|
+
dockerfile: z.ZodOptional<z.ZodString>;
|
|
67
|
+
installCommands: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
68
|
+
commands: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
69
|
+
env: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
70
|
+
buildArgs: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
71
|
+
requiredMetadata: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
72
|
+
requiredVars: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
73
|
+
metadataTypes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
74
|
+
varsTypes: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
75
|
+
smokeTest: z.ZodOptional<z.ZodString>;
|
|
76
|
+
license: z.ZodOptional<z.ZodString>;
|
|
77
|
+
changelog: z.ZodOptional<z.ZodString>;
|
|
78
|
+
homepageUrl: z.ZodOptional<z.ZodString>;
|
|
79
|
+
sourceUrl: z.ZodOptional<z.ZodString>;
|
|
80
|
+
summary: z.ZodOptional<z.ZodString>;
|
|
81
|
+
documentationUrl: z.ZodOptional<z.ZodString>;
|
|
82
|
+
icon: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodObject<{
|
|
83
|
+
key: z.ZodString;
|
|
84
|
+
badge: z.ZodOptional<z.ZodString>;
|
|
85
|
+
}, z.core.$strict>]>>;
|
|
86
|
+
network: z.ZodOptional<z.ZodObject<{
|
|
87
|
+
egress: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
88
|
+
}, z.core.$strict>>;
|
|
89
|
+
}, z.core.$strict>;
|
|
90
|
+
export type PluginSpecInput = z.infer<typeof PluginSpecSchema>;
|
|
91
|
+
/**
|
|
92
|
+
* Result of checking a parsed YAML document against a package schema:
|
|
93
|
+
* `issues` are the individual problems, `message` the one-line form the upload
|
|
94
|
+
* API reports (`plugin-spec.yaml: <path>: <problem>; …`).
|
|
95
|
+
*/
|
|
96
|
+
export type PackageCheck<T> = {
|
|
97
|
+
ok: true;
|
|
98
|
+
value: T;
|
|
99
|
+
} | {
|
|
100
|
+
ok: false;
|
|
101
|
+
issues: string[];
|
|
102
|
+
message: string;
|
|
103
|
+
};
|
|
104
|
+
/** Check a parsed `plugin-spec.yaml` document against {@link PluginSpecSchema}. */
|
|
105
|
+
export declare function checkPluginSpec(raw: unknown): PackageCheck<PluginSpecInput>;
|
|
106
|
+
/** Check a parsed `config.yaml` document against {@link PluginConfigSchema}. */
|
|
107
|
+
export declare function checkPluginConfig(raw: unknown): PackageCheck<PluginConfigInput>;
|
|
108
|
+
/**
|
|
109
|
+
* The required-field contract: `name` and `version` always, `commands` for
|
|
110
|
+
* every type except `ManualApprovalStep`. Returns the upload's message, or null.
|
|
111
|
+
*/
|
|
112
|
+
export declare function pluginSpecRequiredFieldsProblem(spec: Pick<PluginSpecInput, 'name' | 'version' | 'commands' | 'pluginType'>): string | null;
|