@ticatec/omniflow-nexus 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ticatec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # @ticatec/omniflow-nexus
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg)](https://nodejs.org/)
5
+
6
+ [中文文档](./README_CN.md)
7
+
8
+ Official Sonatype Nexus 3 artifact repository driver for OmniFlow. Provides full-stack enterprise artifact publishing for **Maven** (`maven-releases`/`snapshots`), **NPM** (`npm-hosted`), **Docker** (Docker hosted), and **Raw** (generic binary/archives).
9
+
10
+ ---
11
+
12
+ ## Features
13
+
14
+ - **Maven Package Registry**: Direct HTTP PUT upload for Java JAR and POM packages without needing a full local JDK/Maven toolchain (`NexusMavenPublisher`).
15
+ - **NPM Package Registry**: Automatic `.npmrc` authentication injection (`_auth` / `_authToken`) for publishing scoped or public packages (`NexusNpmPublisher`).
16
+ - **Docker Registry**: Support for connector-port and repository-path based Docker hosted repositories (`NexusDockerPublisher`).
17
+ - **Raw (Generic) Registry**: Direct HTTP PUT upload for frontend distribution archives (`.tar.gz`/`.zip`) or binaries (`NexusRawPublisher`). Also implements `download()`, which `deploy.web` uses to fetch an archive by name and version.
18
+ - **Flexible Authentication**: HTTP Basic Authentication (`username:password`) and Bearer Token support.
19
+
20
+ ---
21
+
22
+ ## How to Register
23
+
24
+ ### 1. One-Click Registration (Recommended)
25
+
26
+ ```typescript
27
+ import { defaultArtifactPublisherRegistry } from '@ticatec/omniflow-artifact'
28
+ import { registerNexus } from '@ticatec/omniflow-nexus'
29
+
30
+ // Register all Nexus publishers (Maven + NPM + Docker + Raw)
31
+ registerNexus({ artifactRegistry: defaultArtifactPublisherRegistry })
32
+ ```
33
+
34
+ ### 2. Granular Registration
35
+
36
+ ```typescript
37
+ import { registerArtifactPublisher } from '@ticatec/omniflow-artifact'
38
+ import {
39
+ NexusMavenPublisher,
40
+ NexusNpmPublisher,
41
+ NexusDockerPublisher,
42
+ NexusRawPublisher
43
+ } from '@ticatec/omniflow-nexus'
44
+
45
+ registerArtifactPublisher(new NexusMavenPublisher())
46
+ registerArtifactPublisher(new NexusNpmPublisher())
47
+ registerArtifactPublisher(new NexusDockerPublisher())
48
+ registerArtifactPublisher(new NexusRawPublisher())
49
+ ```
50
+
51
+ ---
52
+
53
+ ## Configuration Example (`omniflow.yaml`)
54
+
55
+ ```yaml
56
+ omniflow:
57
+ registries:
58
+ # 1. Nexus Maven Hosted Repository
59
+ maven:
60
+ nexus:
61
+ server: http://nexus.mycompany.com:8081
62
+ namespace: maven-releases
63
+ username: ${NEXUS_USER}
64
+ password: ${NEXUS_PASSWORD}
65
+
66
+ # 2. Nexus NPM Hosted Repository
67
+ npm:
68
+ nexus:
69
+ server: http://nexus.mycompany.com:8081
70
+ namespace: npm-hosted
71
+ username: ${NEXUS_USER}
72
+ password: ${NEXUS_PASSWORD}
73
+
74
+ # 3. Nexus Docker Hosted Repository
75
+ docker:
76
+ nexus:
77
+ server: nexus.mycompany.com:8082
78
+ username: ${NEXUS_USER}
79
+ password: ${NEXUS_PASSWORD}
80
+
81
+ # 4. Nexus Raw (Generic) Repository
82
+ generic:
83
+ nexus:
84
+ server: http://nexus.mycompany.com:8081
85
+ namespace: raw-hosted
86
+ username: ${NEXUS_USER}
87
+ password: ${NEXUS_PASSWORD}
88
+ ```
89
+
90
+ ---
91
+
92
+ ## License
93
+
94
+ MIT License.
package/README_CN.md ADDED
@@ -0,0 +1,94 @@
1
+ # @ticatec/omniflow-nexus
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Node.js Version](https://img.shields.io/badge/node-%3E%3D20.0.0-brightgreen.svg)](https://nodejs.org/)
5
+
6
+ [English Documentation](./README.md)
7
+
8
+ OmniFlow 的 Sonatype Nexus 3 官方私有制品库驱动插件。专精于企业自建制品管理生态,提供 **Maven**(`maven-releases`/`snapshots`)、**NPM**(`npm-hosted`)、**Docker**(Docker hosted)和 **Raw**(通用归档/二进制)全栈发布能力。
9
+
10
+ ---
11
+
12
+ ## 特性
13
+
14
+ - **Maven 制品库**:直接通过 HTTP PUT 上传 Java JAR 与 POM 包,无需在 CI 容器中安装完整 JDK/Maven 工具链 (`NexusMavenPublisher`)。
15
+ - **NPM 制品库**:自动向 `.npmrc` 注入 Base64 认证串 (`_auth`) 或 Token (`_authToken`),支持 scoped 或公有 npm 包发布 (`NexusNpmPublisher`)。
16
+ - **Docker 容器镜像**:支持独立 HTTP 端口连接器模式或路径路由模式的 Docker hosted 镜像仓库推送 (`NexusDockerPublisher`)。
17
+ - **Raw 通用归档**:直接通过 HTTP PUT 上传前端产物压缩包 (`.tar.gz`/`.zip`) 或二进制发行文件至 raw 仓库 (`NexusRawPublisher`);同时实现 `download()`,`deploy.web` 用它按名称和版本取回归档。
18
+ - **灵活认证机制**:支持 HTTP Basic Auth (`username:password`) 与 Bearer Token。
19
+
20
+ ---
21
+
22
+ ## 如何注册
23
+
24
+ ### 1. 一键全量注册(推荐)
25
+
26
+ ```typescript
27
+ import { defaultArtifactPublisherRegistry } from '@ticatec/omniflow-artifact'
28
+ import { registerNexus } from '@ticatec/omniflow-nexus'
29
+
30
+ // 注册所有 Nexus 驱动(Maven + NPM + Docker + Raw 通用归档)
31
+ registerNexus({ artifactRegistry: defaultArtifactPublisherRegistry })
32
+ ```
33
+
34
+ ### 2. 按需单项注册
35
+
36
+ ```typescript
37
+ import { registerArtifactPublisher } from '@ticatec/omniflow-artifact'
38
+ import {
39
+ NexusMavenPublisher,
40
+ NexusNpmPublisher,
41
+ NexusDockerPublisher,
42
+ NexusRawPublisher
43
+ } from '@ticatec/omniflow-nexus'
44
+
45
+ registerArtifactPublisher(new NexusMavenPublisher())
46
+ registerArtifactPublisher(new NexusNpmPublisher())
47
+ registerArtifactPublisher(new NexusDockerPublisher())
48
+ registerArtifactPublisher(new NexusRawPublisher())
49
+ ```
50
+
51
+ ---
52
+
53
+ ## 配置示例 (`omniflow.yaml`)
54
+
55
+ ```yaml
56
+ omniflow:
57
+ registries:
58
+ # 1. Nexus Maven 宿主仓库
59
+ maven:
60
+ nexus:
61
+ server: http://nexus.mycompany.com:8081
62
+ namespace: maven-releases
63
+ username: ${NEXUS_USER}
64
+ password: ${NEXUS_PASSWORD}
65
+
66
+ # 2. Nexus NPM 宿主仓库
67
+ npm:
68
+ nexus:
69
+ server: http://nexus.mycompany.com:8081
70
+ namespace: npm-hosted
71
+ username: ${NEXUS_USER}
72
+ password: ${NEXUS_PASSWORD}
73
+
74
+ # 3. Nexus Docker 宿主仓库
75
+ docker:
76
+ nexus:
77
+ server: nexus.mycompany.com:8082
78
+ username: ${NEXUS_USER}
79
+ password: ${NEXUS_PASSWORD}
80
+
81
+ # 4. Nexus Raw 通用归档仓库
82
+ generic:
83
+ nexus:
84
+ server: http://nexus.mycompany.com:8081
85
+ namespace: raw-hosted
86
+ username: ${NEXUS_USER}
87
+ password: ${NEXUS_PASSWORD}
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 许可证
93
+
94
+ MIT License.
@@ -0,0 +1,42 @@
1
+ import { maskSecrets, safeFetch, extractErrorMessage, type SafeFetchOptions } from '@ticatec/omniflow-artifact';
2
+ export interface NexusClientConfig {
3
+ baseUrl: string;
4
+ username?: string;
5
+ password?: string;
6
+ token?: string;
7
+ timeoutMs?: number;
8
+ }
9
+ export declare class NexusClient {
10
+ readonly baseUrl: string;
11
+ readonly username?: string;
12
+ readonly password?: string;
13
+ readonly token?: string;
14
+ readonly timeoutMs: number;
15
+ constructor(config: NexusClientConfig);
16
+ get host(): string;
17
+ get hostname(): string;
18
+ /**
19
+ * Return sensitive credential strings of length >= 3 for scrubbing.
20
+ * Username is intentionally excluded to preserve debugging visibility.
21
+ */
22
+ getSecrets(): string[];
23
+ maskSecrets(input: string): string;
24
+ extractErrorMessage(response: Response): Promise<string>;
25
+ getAuthHeaders(): Record<string, string>;
26
+ /**
27
+ * Resolve root repository URL for a given repository name.
28
+ * Handles cases where baseUrl might already contain "/repository/<name>".
29
+ */
30
+ getRepositoryBaseUrl(repoName?: string): string;
31
+ /**
32
+ * Build URL for Maven artifact.
33
+ */
34
+ getMavenArtifactUrl(repoName: string, groupId: string, artifactId: string, version: string, filename: string): string;
35
+ /**
36
+ * Build URL for Raw (Generic) artifact.
37
+ */
38
+ getRawArtifactUrl(repoName: string, subpath: string, filename: string): string;
39
+ request(url: string, init?: RequestInit): Promise<Response>;
40
+ }
41
+ export { maskSecrets, safeFetch, extractErrorMessage, type SafeFetchOptions };
42
+ //# sourceMappingURL=NexusClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NexusClient.d.ts","sourceRoot":"","sources":["../../src/client/NexusClient.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,WAAW,EACX,SAAS,EACT,mBAAmB,EACnB,KAAK,gBAAgB,EACtB,MAAM,4BAA4B,CAAA;AAEnC,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,WAAW;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;gBAEd,MAAM,EAAE,iBAAiB;IAYrC,IAAI,IAAI,IAAI,MAAM,CAGjB;IAED,IAAI,QAAQ,IAAI,MAAM,CAGrB;IAED;;;OAGG;IACH,UAAU,IAAI,MAAM,EAAE;IAatB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAI5B,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAI9D,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAWxC;;;OAGG;IACH,oBAAoB,CAAC,QAAQ,SAAK,GAAG,MAAM;IAkB3C;;OAEG;IACH,mBAAmB,CACjB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,MAAM,GACf,MAAM;IAMT;;OAEG;IACH,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM;IAMxE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC;CAatE;AAED,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,mBAAmB,EAAE,KAAK,gBAAgB,EAAE,CAAA"}
@@ -0,0 +1,106 @@
1
+ import { maskSecrets, safeFetch, extractErrorMessage } from '@ticatec/omniflow-artifact';
2
+ export class NexusClient {
3
+ baseUrl;
4
+ username;
5
+ password;
6
+ token;
7
+ timeoutMs;
8
+ constructor(config) {
9
+ let base = config.baseUrl.trim().replace(/\/+$/, '');
10
+ if (!/^https?:\/\//i.test(base)) {
11
+ base = `https://${base}`;
12
+ }
13
+ this.baseUrl = base;
14
+ this.username = config.username;
15
+ this.password = config.password;
16
+ this.token = config.token;
17
+ this.timeoutMs = config.timeoutMs ?? 30000;
18
+ }
19
+ get host() {
20
+ const parsed = new URL(this.baseUrl);
21
+ return parsed.host;
22
+ }
23
+ get hostname() {
24
+ const parsed = new URL(this.baseUrl);
25
+ return parsed.hostname;
26
+ }
27
+ /**
28
+ * Return sensitive credential strings of length >= 3 for scrubbing.
29
+ * Username is intentionally excluded to preserve debugging visibility.
30
+ */
31
+ getSecrets() {
32
+ const secrets = [this.token, this.password].filter((s) => typeof s === 'string' && s.length >= 3);
33
+ if (this.username && this.password) {
34
+ const basic = Buffer.from(`${this.username}:${this.password}`).toString('base64');
35
+ if (basic.length >= 3) {
36
+ secrets.push(basic);
37
+ }
38
+ }
39
+ return secrets;
40
+ }
41
+ maskSecrets(input) {
42
+ return maskSecrets(input, this.getSecrets());
43
+ }
44
+ async extractErrorMessage(response) {
45
+ return extractErrorMessage(response, this.getSecrets());
46
+ }
47
+ getAuthHeaders() {
48
+ const headers = {};
49
+ if (this.token) {
50
+ headers['Authorization'] = `Bearer ${this.token}`;
51
+ }
52
+ else if (this.username && this.password) {
53
+ const basic = Buffer.from(`${this.username}:${this.password}`).toString('base64');
54
+ headers['Authorization'] = `Basic ${basic}`;
55
+ }
56
+ return headers;
57
+ }
58
+ /**
59
+ * Resolve root repository URL for a given repository name.
60
+ * Handles cases where baseUrl might already contain "/repository/<name>".
61
+ */
62
+ getRepositoryBaseUrl(repoName = '') {
63
+ let cleanBase = this.baseUrl.replace(/\/+$/, '');
64
+ if (cleanBase.includes('/repository/')) {
65
+ const idx = cleanBase.indexOf('/repository/');
66
+ const root = cleanBase.substring(0, idx);
67
+ const existingRepo = cleanBase.substring(idx + '/repository/'.length).split('/')[0];
68
+ const targetRepo = repoName || existingRepo;
69
+ return `${root}/repository/${targetRepo}`;
70
+ }
71
+ if (!repoName) {
72
+ return `${cleanBase}/repository`;
73
+ }
74
+ return `${cleanBase}/repository/${repoName.replace(/^\/+/, '').replace(/\/+$/, '')}`;
75
+ }
76
+ /**
77
+ * Build URL for Maven artifact.
78
+ */
79
+ getMavenArtifactUrl(repoName, groupId, artifactId, version, filename) {
80
+ const base = this.getRepositoryBaseUrl(repoName);
81
+ const groupPath = groupId.replace(/\./g, '/');
82
+ return `${base}/${groupPath}/${artifactId}/${version}/${filename}`;
83
+ }
84
+ /**
85
+ * Build URL for Raw (Generic) artifact.
86
+ */
87
+ getRawArtifactUrl(repoName, subpath, filename) {
88
+ const base = this.getRepositoryBaseUrl(repoName);
89
+ const cleanSubpath = subpath ? subpath.replace(/^\/+/, '').replace(/\/+$/, '') : '';
90
+ return cleanSubpath ? `${base}/${cleanSubpath}/${filename}` : `${base}/${filename}`;
91
+ }
92
+ async request(url, init = {}) {
93
+ const headers = {
94
+ ...this.getAuthHeaders(),
95
+ ...(init.headers || {})
96
+ };
97
+ return safeFetch(url, {
98
+ ...init,
99
+ headers,
100
+ timeoutMs: this.timeoutMs,
101
+ secrets: this.getSecrets()
102
+ });
103
+ }
104
+ }
105
+ export { maskSecrets, safeFetch, extractErrorMessage };
106
+ //# sourceMappingURL=NexusClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NexusClient.js","sourceRoot":"","sources":["../../src/client/NexusClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import { BaseDockerPublisher } from '@ticatec/omniflow-artifact';
2
+ import type { RegistryConfig } from '@ticatec/omniflow-artifact';
3
+ /**
4
+ * Sonatype Nexus 3 Docker Registry Publisher.
5
+ *
6
+ * Supports Nexus Docker hosted repositories via:
7
+ * 1. Dedicated HTTP connector port (e.g. nexus.example.com:8082/my-app:tag)
8
+ * 2. Repository path routing (e.g. nexus.example.com/repository/docker-hosted/my-app:tag)
9
+ */
10
+ export declare class NexusDockerPublisher extends BaseDockerPublisher {
11
+ readonly id = "nexus-docker";
12
+ readonly name = "Nexus 3 Docker Registry";
13
+ readonly platform = "nexus";
14
+ readonly priority = 20;
15
+ detect(registry: RegistryConfig): boolean;
16
+ buildRepositoryUrl(registry: RegistryConfig, imageName: string): string;
17
+ }
18
+ //# sourceMappingURL=NexusDockerPublisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NexusDockerPublisher.d.ts","sourceRoot":"","sources":["../../src/docker/NexusDockerPublisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAEhE;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,mBAAmB;IAC3D,QAAQ,CAAC,EAAE,kBAAiB;IAC5B,QAAQ,CAAC,IAAI,6BAA4B;IACzC,QAAQ,CAAC,QAAQ,WAAU;IAC3B,SAAkB,QAAQ,MAAK;IAEtB,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO;IAkCzC,kBAAkB,CAAC,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM;CAejF"}
@@ -0,0 +1,56 @@
1
+ import { BaseDockerPublisher } from '@ticatec/omniflow-artifact';
2
+ /**
3
+ * Sonatype Nexus 3 Docker Registry Publisher.
4
+ *
5
+ * Supports Nexus Docker hosted repositories via:
6
+ * 1. Dedicated HTTP connector port (e.g. nexus.example.com:8082/my-app:tag)
7
+ * 2. Repository path routing (e.g. nexus.example.com/repository/docker-hosted/my-app:tag)
8
+ */
9
+ export class NexusDockerPublisher extends BaseDockerPublisher {
10
+ id = 'nexus-docker';
11
+ name = 'Nexus 3 Docker Registry';
12
+ platform = 'nexus';
13
+ priority = 20;
14
+ detect(registry) {
15
+ if (registry.type !== 'docker' && registry.type !== 'container') {
16
+ return false;
17
+ }
18
+ const regName = (registry.name || '').toLowerCase();
19
+ if (regName === 'nexus' || regName.startsWith('nexus-') || regName === 'nexus-docker') {
20
+ return true;
21
+ }
22
+ const server = (registry.server || '').toLowerCase();
23
+ try {
24
+ const parsed = new URL(server.includes('://') ? server : `https://${server}`);
25
+ const host = parsed.hostname.toLowerCase();
26
+ // Exclude other known platforms
27
+ if (host === 'aliyun.com' ||
28
+ host.endsWith('.aliyun.com') ||
29
+ host.endsWith('.aliyuncs.com') ||
30
+ host === 'gitlab.com' ||
31
+ host.endsWith('.gitlab.com') ||
32
+ host === 'github.com' ||
33
+ host.endsWith('.github.com')) {
34
+ return false;
35
+ }
36
+ return host.includes('nexus') || parsed.pathname.includes('/repository/docker');
37
+ }
38
+ catch {
39
+ return false;
40
+ }
41
+ }
42
+ buildRepositoryUrl(registry, imageName) {
43
+ let host = this.normalizeServerHost(registry.server);
44
+ const cleanImage = imageName.replace(/^\/+/, '');
45
+ // Check if server or namespace includes repository path
46
+ const ns = (registry.namespace || '').replace(/\/+$/, '');
47
+ if (ns) {
48
+ if (cleanImage.startsWith(`${ns}/`)) {
49
+ return `${host}/${cleanImage}`;
50
+ }
51
+ return `${host}/${ns}/${cleanImage}`;
52
+ }
53
+ return `${host}/${cleanImage}`;
54
+ }
55
+ }
56
+ //# sourceMappingURL=NexusDockerPublisher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NexusDockerPublisher.js","sourceRoot":"","sources":["../../src/docker/NexusDockerPublisher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAGhE;;;;;;GAMG;AACH,MAAM,OAAO,oBAAqB,SAAQ,mBAAmB;IAClD,EAAE,GAAG,cAAc,CAAA;IACnB,IAAI,GAAG,yBAAyB,CAAA;IAChC,QAAQ,GAAG,OAAO,CAAA;IACT,QAAQ,GAAG,EAAE,CAAA;IAEtB,MAAM,CAAC,QAAwB;QACtC,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ,IAAI,QAAQ,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YAChE,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;QACnD,IAAI,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,OAAO,KAAK,cAAc,EAAE,CAAC;YACtF,OAAO,IAAI,CAAA;QACb,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,QAAQ,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAA;QACpD,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,EAAE,CAAC,CAAA;YAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAA;YAE1C,gCAAgC;YAChC,IACE,IAAI,KAAK,YAAY;gBACrB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAC5B,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC;gBAC9B,IAAI,KAAK,YAAY;gBACrB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC;gBAC5B,IAAI,KAAK,YAAY;gBACrB,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,EAC5B,CAAC;gBACD,OAAO,KAAK,CAAA;YACd,CAAC;YAED,OAAO,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAA;QACjF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAEQ,kBAAkB,CAAC,QAAwB,EAAE,SAAiB;QACrE,IAAI,IAAI,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QACpD,MAAM,UAAU,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QAEhD,wDAAwD;QACxD,MAAM,EAAE,GAAG,CAAC,QAAQ,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAA;QACzD,IAAI,EAAE,EAAE,CAAC;YACP,IAAI,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC;gBACpC,OAAO,GAAG,IAAI,IAAI,UAAU,EAAE,CAAA;YAChC,CAAC;YACD,OAAO,GAAG,IAAI,IAAI,EAAE,IAAI,UAAU,EAAE,CAAA;QACtC,CAAC;QAED,OAAO,GAAG,IAAI,IAAI,UAAU,EAAE,CAAA;IAChC,CAAC;CACF"}
@@ -0,0 +1,29 @@
1
+ import type { PluginContext } from '@ticatec/omniflow-core';
2
+ import type { ArtifactPublisherRegistry } from '@ticatec/omniflow-artifact';
3
+ import { NexusMavenPublisher } from './maven/NexusMavenPublisher.js';
4
+ import { NexusNpmPublisher } from './npm/NexusNpmPublisher.js';
5
+ import { NexusDockerPublisher } from './docker/NexusDockerPublisher.js';
6
+ import { NexusRawPublisher } from './raw/NexusRawPublisher.js';
7
+ export * from './client/NexusClient.js';
8
+ export * from './maven/NexusMavenPublisher.js';
9
+ export * from './npm/NexusNpmPublisher.js';
10
+ export * from './docker/NexusDockerPublisher.js';
11
+ export * from './raw/NexusRawPublisher.js';
12
+ export interface RegisterNexusOptions {
13
+ artifactRegistry?: ArtifactPublisherRegistry;
14
+ }
15
+ /**
16
+ * Standard OmniFlow Plugin SPI entry point.
17
+ */
18
+ export declare function register(ctx: PluginContext, options?: Record<string, unknown>): void;
19
+ export default register;
20
+ /**
21
+ * Register all Sonatype Nexus 3 artifact publishers into the target registry.
22
+ */
23
+ export declare function registerNexus(options?: RegisterNexusOptions): {
24
+ mavenPublisher: NexusMavenPublisher;
25
+ npmPublisher: NexusNpmPublisher;
26
+ dockerPublisher: NexusDockerPublisher;
27
+ rawPublisher: NexusRawPublisher;
28
+ };
29
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAC3D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,4BAA4B,CAAA;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAE9D,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kCAAkC,CAAA;AAChD,cAAc,4BAA4B,CAAA;AAE1C,MAAM,WAAW,oBAAoB;IACnC,gBAAgB,CAAC,EAAE,yBAAyB,CAAA;CAC7C;AAED;;GAEG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,IAAI,CAExF;AAED,eAAe,QAAQ,CAAA;AAEvB;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,GAAE,oBAAyB,GAAG;IACjE,cAAc,EAAE,mBAAmB,CAAA;IACnC,YAAY,EAAE,iBAAiB,CAAA;IAC/B,eAAe,EAAE,oBAAoB,CAAA;IACrC,YAAY,EAAE,iBAAiB,CAAA;CAChC,CAmBA"}
package/dist/index.js ADDED
@@ -0,0 +1,38 @@
1
+ import { NexusMavenPublisher } from './maven/NexusMavenPublisher.js';
2
+ import { NexusNpmPublisher } from './npm/NexusNpmPublisher.js';
3
+ import { NexusDockerPublisher } from './docker/NexusDockerPublisher.js';
4
+ import { NexusRawPublisher } from './raw/NexusRawPublisher.js';
5
+ export * from './client/NexusClient.js';
6
+ export * from './maven/NexusMavenPublisher.js';
7
+ export * from './npm/NexusNpmPublisher.js';
8
+ export * from './docker/NexusDockerPublisher.js';
9
+ export * from './raw/NexusRawPublisher.js';
10
+ /**
11
+ * Standard OmniFlow Plugin SPI entry point.
12
+ */
13
+ export function register(ctx, options = {}) {
14
+ registerNexus({ artifactRegistry: ctx.artifactRegistry });
15
+ }
16
+ export default register;
17
+ /**
18
+ * Register all Sonatype Nexus 3 artifact publishers into the target registry.
19
+ */
20
+ export function registerNexus(options = {}) {
21
+ const mavenPublisher = new NexusMavenPublisher();
22
+ const npmPublisher = new NexusNpmPublisher();
23
+ const dockerPublisher = new NexusDockerPublisher();
24
+ const rawPublisher = new NexusRawPublisher();
25
+ if (options.artifactRegistry) {
26
+ options.artifactRegistry.register(mavenPublisher);
27
+ options.artifactRegistry.register(npmPublisher);
28
+ options.artifactRegistry.register(dockerPublisher);
29
+ options.artifactRegistry.register(rawPublisher);
30
+ }
31
+ return {
32
+ mavenPublisher,
33
+ npmPublisher,
34
+ dockerPublisher,
35
+ rawPublisher
36
+ };
37
+ }
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAA;AACvE,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AAE9D,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kCAAkC,CAAA;AAChD,cAAc,4BAA4B,CAAA;AAM1C;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,GAAkB,EAAE,UAAmC,EAAE;IAChF,aAAa,CAAC,EAAE,gBAAgB,EAAE,GAAG,CAAC,gBAAgB,EAAE,CAAC,CAAA;AAC3D,CAAC;AAED,eAAe,QAAQ,CAAA;AAEvB;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,UAAgC,EAAE;IAM9D,MAAM,cAAc,GAAG,IAAI,mBAAmB,EAAE,CAAA;IAChD,MAAM,YAAY,GAAG,IAAI,iBAAiB,EAAE,CAAA;IAC5C,MAAM,eAAe,GAAG,IAAI,oBAAoB,EAAE,CAAA;IAClD,MAAM,YAAY,GAAG,IAAI,iBAAiB,EAAE,CAAA;IAE5C,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;QACjD,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;QAC/C,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAA;QAClD,OAAO,CAAC,gBAAgB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;IACjD,CAAC;IAED,OAAO;QACL,cAAc;QACd,YAAY;QACZ,eAAe;QACf,YAAY;KACb,CAAA;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ import { BasePublisher } from '@ticatec/omniflow-artifact';
2
+ import type { ArtifactPayload, PublishOptions, RegistryConfig } from '@ticatec/omniflow-artifact';
3
+ /**
4
+ * Sonatype Nexus 3 Maven Repository Publisher.
5
+ *
6
+ * Endpoint format: PUT {server}/repository/{repoName}/{groupId-as-path}/{artifactId}/{version}/{filename}
7
+ * Typically used with repositories like "maven-releases" or "maven-snapshots".
8
+ */
9
+ export declare class NexusMavenPublisher extends BasePublisher {
10
+ readonly id = "nexus-maven";
11
+ readonly name = "Nexus 3 Maven Repository";
12
+ readonly platform = "nexus";
13
+ readonly artifactType = "maven";
14
+ readonly priority = 20;
15
+ detect(registry: RegistryConfig): boolean;
16
+ login(registry: RegistryConfig, _options?: PublishOptions): Promise<void>;
17
+ buildTargetRef(artifact: ArtifactPayload, _registry: RegistryConfig): string;
18
+ exists(artifact: ArtifactPayload, registry: RegistryConfig, options?: PublishOptions): Promise<boolean>;
19
+ protected doPublish(artifact: ArtifactPayload, registry: RegistryConfig, options?: PublishOptions): Promise<{
20
+ ref: string;
21
+ digest?: string;
22
+ metadata?: Record<string, unknown>;
23
+ }>;
24
+ }
25
+ //# sourceMappingURL=NexusMavenPublisher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NexusMavenPublisher.d.ts","sourceRoot":"","sources":["../../src/maven/NexusMavenPublisher.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAuE,MAAM,4BAA4B,CAAA;AAC/H,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAGjG;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,QAAQ,CAAC,EAAE,iBAAgB;IAC3B,QAAQ,CAAC,IAAI,8BAA6B;IAC1C,QAAQ,CAAC,QAAQ,WAAU;IAC3B,QAAQ,CAAC,YAAY,WAAU;IAC/B,SAAkB,QAAQ,MAAK;IAEtB,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO;IAkC5C,KAAK,CAAC,QAAQ,EAAE,cAAc,EAAE,QAAQ,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAOtE,cAAc,CAAC,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,cAAc,GAAG,MAAM;IAUtE,MAAM,CACnB,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,OAAO,CAAC;cA0DH,SAAS,CACvB,QAAQ,EAAE,eAAe,EACzB,QAAQ,EAAE,cAAc,EACxB,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC;QACT,GAAG,EAAE,MAAM,CAAA;QACX,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACnC,CAAC;CAwGH"}