@serve.zone/appstore 32.27.0 → 33.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/.smartconfig.json +4 -1
- package/changelog.md +57 -0
- package/dist_catalog/catalog.digest +1 -0
- package/dist_catalog/catalog.envelope.json +7440 -0
- package/{dist_ts_client/data.generated.js → dist_catalog/catalog.json} +6740 -6913
- package/dist_ts_client/catalog.d.ts +16 -0
- package/dist_ts_client/catalog.js +12 -0
- package/dist_ts_client/index.d.ts +3 -1
- package/dist_ts_client/index.js +4 -2
- package/dist_ts_client/loader.d.ts +69 -0
- package/dist_ts_client/loader.js +361 -0
- package/dist_ts_client/plugins.d.ts +5 -0
- package/dist_ts_client/plugins.js +8 -0
- package/dist_ts_client/projection.d.ts +59 -0
- package/dist_ts_client/projection.js +83 -0
- package/dist_ts_client/storage.d.ts +15 -9
- package/dist_ts_client/storage.js +81 -657
- package/dist_ts_client/types.d.ts +86 -41
- package/dist_ts_client/types.js +1 -1
- package/dist_ts_testing/fixtures.d.ts +83 -0
- package/dist_ts_testing/fixtures.js +146 -0
- package/dist_ts_testing/index.d.ts +1 -0
- package/dist_ts_testing/index.js +2 -0
- package/dist_ts_testing/plugins.d.ts +7 -0
- package/dist_ts_testing/plugins.js +11 -0
- package/package.json +15 -10
- package/readme.md +161 -92
- package/ts_client/catalog.ts +26 -0
- package/ts_client/index.ts +3 -1
- package/ts_client/loader.ts +414 -0
- package/ts_client/plugins.ts +10 -0
- package/ts_client/projection.ts +148 -0
- package/ts_client/readme.md +17 -27
- package/ts_client/storage.ts +93 -882
- package/ts_client/types.ts +102 -42
- package/ts_testing/fixtures.ts +230 -0
- package/ts_testing/index.ts +1 -0
- package/ts_testing/plugins.ts +15 -0
- package/ts_testing/tspublish.json +3 -0
- package/apps/adminer/app.json +0 -10
- package/apps/adminer/versions/1.0.0/config.json +0 -6
- package/apps/cloudly/app.json +0 -14
- package/apps/cloudly/versions/1.0.0/config.json +0 -120
- package/apps/cloudly/versions/1.1.0/config.json +0 -120
- package/apps/cloudly/versions/1.1.1/config.json +0 -120
- package/apps/cloudly/versions/1.1.10/config.json +0 -173
- package/apps/cloudly/versions/1.1.2/config.json +0 -130
- package/apps/cloudly/versions/1.1.3/config.json +0 -130
- package/apps/cloudly/versions/1.1.4/config.json +0 -130
- package/apps/cloudly/versions/1.1.5/config.json +0 -149
- package/apps/cloudly/versions/1.1.6/config.json +0 -149
- package/apps/cloudly/versions/1.1.7/config.json +0 -149
- package/apps/cloudly/versions/1.1.8/config.json +0 -173
- package/apps/cloudly/versions/1.1.9/config.json +0 -173
- package/apps/cloudly/versions/1.10.0/config.json +0 -173
- package/apps/cloudly/versions/1.11.0/config.json +0 -173
- package/apps/cloudly/versions/1.12.0/config.json +0 -173
- package/apps/cloudly/versions/1.13.0/config.json +0 -173
- package/apps/cloudly/versions/1.14.0/config.json +0 -173
- package/apps/cloudly/versions/1.15.0/config.json +0 -173
- package/apps/cloudly/versions/1.16.0/config.json +0 -173
- package/apps/cloudly/versions/1.17.0/config.json +0 -173
- package/apps/cloudly/versions/1.18.0/config.json +0 -173
- package/apps/cloudly/versions/1.19.0/config.json +0 -173
- package/apps/cloudly/versions/1.2.0/config.json +0 -173
- package/apps/cloudly/versions/1.2.1/config.json +0 -173
- package/apps/cloudly/versions/1.20.0/config.json +0 -173
- package/apps/cloudly/versions/1.21.0/config.json +0 -173
- package/apps/cloudly/versions/1.22.0/config.json +0 -173
- package/apps/cloudly/versions/1.23.0/config.json +0 -173
- package/apps/cloudly/versions/1.24.0/config.json +0 -173
- package/apps/cloudly/versions/1.25.0/config.json +0 -173
- package/apps/cloudly/versions/1.26.0/config.json +0 -173
- package/apps/cloudly/versions/1.27.0/config.json +0 -173
- package/apps/cloudly/versions/1.3.0/config.json +0 -173
- package/apps/cloudly/versions/1.4.0/config.json +0 -173
- package/apps/cloudly/versions/1.5.0/config.json +0 -173
- package/apps/cloudly/versions/1.6.0/config.json +0 -173
- package/apps/cloudly/versions/1.7.0/config.json +0 -173
- package/apps/cloudly/versions/1.8.0/config.json +0 -173
- package/apps/cloudly/versions/1.9.0/config.json +0 -173
- package/apps/ghost/app.json +0 -10
- package/apps/ghost/versions/1.0.0/config.json +0 -18
- package/apps/gitea/app.json +0 -10
- package/apps/gitea/versions/1.0.0/config.json +0 -16
- package/apps/gitops/app.json +0 -14
- package/apps/gitops/versions/1.0.0/config.json +0 -28
- package/apps/grafana/app.json +0 -10
- package/apps/grafana/versions/1.0.0/config.json +0 -9
- package/apps/mariadb/app.json +0 -10
- package/apps/mariadb/versions/1.0.0/config.json +0 -9
- package/apps/mattermost/app.json +0 -10
- package/apps/mattermost/versions/1.0.0/config.json +0 -6
- package/apps/n8n/app.json +0 -10
- package/apps/n8n/versions/1.0.0/config.json +0 -6
- package/apps/nextcloud/app.json +0 -10
- package/apps/nextcloud/versions/1.0.0/config.json +0 -16
- package/apps/nginx/app.json +0 -10
- package/apps/nginx/versions/1.0.0/config.json +0 -6
- package/apps/openbao/app.json +0 -16
- package/apps/openbao/versions/1.0.0/config.json +0 -52
- package/apps/plausible/app.json +0 -10
- package/apps/plausible/versions/1.0.0/config.json +0 -9
- package/apps/portainer/app.json +0 -10
- package/apps/portainer/versions/1.0.0/config.json +0 -6
- package/apps/postgres/app.json +0 -10
- package/apps/postgres/versions/1.0.0/config.json +0 -11
- package/apps/rustdesk-server/app.json +0 -14
- package/apps/rustdesk-server/versions/1.0.0/config.json +0 -19
- package/apps/siprouter/app.json +0 -14
- package/apps/siprouter/versions/1.0.0/config.json +0 -84
- package/apps/uptime-kuma/app.json +0 -10
- package/apps/uptime-kuma/versions/1.0.0/config.json +0 -6
- package/apps/valkey/app.json +0 -10
- package/apps/valkey/versions/1.0.0/config.json +0 -6
- package/apps/vaultwarden/app.json +0 -10
- package/apps/vaultwarden/versions/1.0.0/config.json +0 -6
- package/apps/wordpress/app.json +0 -10
- package/apps/wordpress/versions/1.0.0/config.json +0 -15
- package/appstore.json +0 -194
- package/dist_ts_client/classes.appstoreresolver.d.ts +0 -59
- package/dist_ts_client/classes.appstoreresolver.js +0 -736
- package/dist_ts_client/data.generated.d.ts +0 -2
- package/ts_client/classes.appstoreresolver.ts +0 -896
- package/ts_client/data.generated.ts +0 -7606
|
@@ -1,736 +0,0 @@
|
|
|
1
|
-
import * as interfaces from '@serve.zone/interfaces';
|
|
2
|
-
import { SmartVersion } from '@push.rocks/smartversion';
|
|
3
|
-
import packageJson from '../package.json' with { type: 'json' };
|
|
4
|
-
import { appStorePackageData } from './data.generated.js';
|
|
5
|
-
import { normalizeAppStoreStorageConfig, validateAppStoreStorageConfig, } from './storage.js';
|
|
6
|
-
export const appStorePackageMetadata = {
|
|
7
|
-
name: packageJson.name,
|
|
8
|
-
version: packageJson.version,
|
|
9
|
-
};
|
|
10
|
-
export const appStoreDefaultRemoteBaseUrl = 'https://code.foss.global/serve.zone/appstore/raw/branch/main';
|
|
11
|
-
export class AppStoreResolver {
|
|
12
|
-
baseUrl;
|
|
13
|
-
fetchRef;
|
|
14
|
-
source;
|
|
15
|
-
resolveDockerDigests;
|
|
16
|
-
requestTimeoutMs;
|
|
17
|
-
now;
|
|
18
|
-
appStoreCache = null;
|
|
19
|
-
inlineAppMetaCache = new Map();
|
|
20
|
-
sourceAppCache = new Map();
|
|
21
|
-
constructor(optionsArg = {}) {
|
|
22
|
-
this.source = optionsArg.source || (optionsArg.baseUrl || optionsArg.fetch ? 'remote' : 'package');
|
|
23
|
-
this.baseUrl = optionsArg.baseUrl || appStoreDefaultRemoteBaseUrl;
|
|
24
|
-
this.fetchRef = optionsArg.fetch || fetch;
|
|
25
|
-
this.resolveDockerDigests = optionsArg.resolveDockerDigests ?? true;
|
|
26
|
-
this.requestTimeoutMs = optionsArg.requestTimeoutMs ?? 30_000;
|
|
27
|
-
if (!Number.isSafeInteger(this.requestTimeoutMs) || this.requestTimeoutMs < 1) {
|
|
28
|
-
throw new Error('App Store requestTimeoutMs must be a positive integer');
|
|
29
|
-
}
|
|
30
|
-
this.now = optionsArg.now || (() => new Date());
|
|
31
|
-
}
|
|
32
|
-
getSourceInfo() {
|
|
33
|
-
return {
|
|
34
|
-
source: this.source,
|
|
35
|
-
packageName: appStorePackageMetadata.name,
|
|
36
|
-
packageVersion: appStorePackageMetadata.version,
|
|
37
|
-
...(this.source === 'remote' ? { baseUrl: this.baseUrl } : {}),
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
async getAppStoreIndex() {
|
|
41
|
-
if (this.appStoreCache) {
|
|
42
|
-
return this.appStoreCache;
|
|
43
|
-
}
|
|
44
|
-
const appStore = await this.fetchAppStoreIndex();
|
|
45
|
-
this.appStoreCache = await this.resolveAppStore(appStore);
|
|
46
|
-
return this.appStoreCache;
|
|
47
|
-
}
|
|
48
|
-
async getApps() {
|
|
49
|
-
return (await this.getAppStoreIndex()).apps;
|
|
50
|
-
}
|
|
51
|
-
async getAppMeta(appIdArg) {
|
|
52
|
-
const app = await this.getAppStoreApp(appIdArg);
|
|
53
|
-
if (!app) {
|
|
54
|
-
throw new Error(`App Store app '${appIdArg}' is not present in the resolved index`);
|
|
55
|
-
}
|
|
56
|
-
if (app?.source?.type === 'repoManifest') {
|
|
57
|
-
return (await this.resolveRepoManifestSource(app.source, app)).appMeta;
|
|
58
|
-
}
|
|
59
|
-
if (app?.source?.type === 'dockerImage') {
|
|
60
|
-
return this.createAppMetaFromAppStoreApp(app);
|
|
61
|
-
}
|
|
62
|
-
const appMeta = this.inlineAppMetaCache.get(appIdArg);
|
|
63
|
-
if (!appMeta) {
|
|
64
|
-
throw new Error(`App Store metadata for '${appIdArg}' is unavailable`);
|
|
65
|
-
}
|
|
66
|
-
return structuredClone(appMeta);
|
|
67
|
-
}
|
|
68
|
-
async getAppVersionConfig(appIdArg, versionArg) {
|
|
69
|
-
const app = await this.getAppStoreApp(appIdArg);
|
|
70
|
-
if (app?.source?.type === 'repoManifest') {
|
|
71
|
-
const resolvedApp = await this.resolveRepoManifestSource(app.source, app);
|
|
72
|
-
const config = resolvedApp.configsByVersion.get(versionArg);
|
|
73
|
-
if (!config) {
|
|
74
|
-
throw new Error(`Version '${versionArg}' is not defined by the linked appstore manifest`);
|
|
75
|
-
}
|
|
76
|
-
this.validateAppStoreVersionConfig(config, `${appIdArg}@${versionArg}`);
|
|
77
|
-
return config;
|
|
78
|
-
}
|
|
79
|
-
if (app?.source?.type === 'dockerImage' && app.runtime) {
|
|
80
|
-
const config = { ...app.runtime };
|
|
81
|
-
await this.applyDockerImageSourceToConfig(app.source, config, versionArg);
|
|
82
|
-
this.validateAppStoreVersionConfig(config, `${appIdArg}@${versionArg}`);
|
|
83
|
-
return config;
|
|
84
|
-
}
|
|
85
|
-
let config;
|
|
86
|
-
try {
|
|
87
|
-
config = await this.fetchJson(`apps/${appIdArg}/versions/${versionArg}/config.json`);
|
|
88
|
-
}
|
|
89
|
-
catch (error) {
|
|
90
|
-
if (app?.source?.type !== 'dockerImage') {
|
|
91
|
-
throw error;
|
|
92
|
-
}
|
|
93
|
-
const appMeta = await this.fetchJson(`apps/${appIdArg}/app.json`);
|
|
94
|
-
config = await this.fetchJson(`apps/${appIdArg}/versions/${appMeta.latestVersion}/config.json`);
|
|
95
|
-
}
|
|
96
|
-
if (app?.source?.type === 'dockerImage') {
|
|
97
|
-
await this.applyDockerImageSourceToConfig(app.source, config, versionArg);
|
|
98
|
-
}
|
|
99
|
-
this.validateAppStoreVersionConfig(config, `${appIdArg}@${versionArg}`);
|
|
100
|
-
return config;
|
|
101
|
-
}
|
|
102
|
-
async resolveAppStore(appStoreArg) {
|
|
103
|
-
const appStore = parseAppStoreIndex(appStoreArg);
|
|
104
|
-
this.sourceAppCache.clear();
|
|
105
|
-
this.inlineAppMetaCache.clear();
|
|
106
|
-
const apps = [];
|
|
107
|
-
for (const app of appStore.apps) {
|
|
108
|
-
apps.push(await this.resolveAppStoreApp(app));
|
|
109
|
-
}
|
|
110
|
-
return {
|
|
111
|
-
...appStore,
|
|
112
|
-
apps,
|
|
113
|
-
resolvedAt: this.now().toISOString(),
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
async resolveRepoManifestSource(sourceArg, appArg) {
|
|
117
|
-
const cacheKey = `${sourceArg.url}#${sourceArg.ref || ''}`;
|
|
118
|
-
const cachedApp = this.sourceAppCache.get(cacheKey);
|
|
119
|
-
if (cachedApp) {
|
|
120
|
-
return cachedApp;
|
|
121
|
-
}
|
|
122
|
-
const manifestText = await this.fetchTextFromUrl(sourceArg.url);
|
|
123
|
-
const manifestHash = await createSha256Hex(manifestText);
|
|
124
|
-
const manifest = parseServezoneAppStoreManifest(JSON.parse(manifestText));
|
|
125
|
-
const resolvedApp = await this.resolveServezoneAppStoreManifest(manifest, {
|
|
126
|
-
type: 'repoManifest',
|
|
127
|
-
url: sourceArg.url,
|
|
128
|
-
ref: sourceArg.ref,
|
|
129
|
-
manifestHash,
|
|
130
|
-
resolvedAt: this.now().toISOString(),
|
|
131
|
-
});
|
|
132
|
-
if (appArg) {
|
|
133
|
-
resolvedApp.appStoreApp = {
|
|
134
|
-
...resolvedApp.appStoreApp,
|
|
135
|
-
...withoutUndefined(appArg),
|
|
136
|
-
latestVersion: resolvedApp.appStoreApp.latestVersion,
|
|
137
|
-
versions: resolvedApp.appStoreApp.versions,
|
|
138
|
-
source: appArg.source,
|
|
139
|
-
tags: appArg.tags || resolvedApp.appStoreApp.tags,
|
|
140
|
-
resolvedSource: resolvedApp.appStoreApp.resolvedSource,
|
|
141
|
-
};
|
|
142
|
-
resolvedApp.appMeta = {
|
|
143
|
-
...resolvedApp.appMeta,
|
|
144
|
-
id: resolvedApp.appStoreApp.id,
|
|
145
|
-
name: resolvedApp.appStoreApp.name,
|
|
146
|
-
description: resolvedApp.appStoreApp.description,
|
|
147
|
-
category: resolvedApp.appStoreApp.category,
|
|
148
|
-
iconName: resolvedApp.appStoreApp.iconName,
|
|
149
|
-
latestVersion: resolvedApp.appStoreApp.latestVersion,
|
|
150
|
-
versions: resolvedApp.appStoreApp.versions || resolvedApp.appMeta.versions,
|
|
151
|
-
tags: resolvedApp.appStoreApp.tags,
|
|
152
|
-
source: appArg.source,
|
|
153
|
-
resolvedSource: resolvedApp.appStoreApp.resolvedSource,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
this.sourceAppCache.set(cacheKey, resolvedApp);
|
|
157
|
-
return resolvedApp;
|
|
158
|
-
}
|
|
159
|
-
async resolveDockerImageSource(sourceArg) {
|
|
160
|
-
let imageDigest;
|
|
161
|
-
if (sourceArg.tracking === 'digest' && this.resolveDockerDigests) {
|
|
162
|
-
imageDigest = await this.resolveDockerImageDigest(sourceArg.image) || undefined;
|
|
163
|
-
}
|
|
164
|
-
return {
|
|
165
|
-
type: 'dockerImage',
|
|
166
|
-
image: sourceArg.image,
|
|
167
|
-
imageDigest,
|
|
168
|
-
resolvedAt: this.now().toISOString(),
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
async resolveDockerImageDigest(imageArg) {
|
|
172
|
-
const parsedImage = parseDockerImageReference(imageArg);
|
|
173
|
-
if (parsedImage.digest) {
|
|
174
|
-
return parsedImage.digest;
|
|
175
|
-
}
|
|
176
|
-
return await this.fetchDockerManifestDigest(parsedImage);
|
|
177
|
-
}
|
|
178
|
-
validateAppStoreVersionConfig(configArg, labelArg = 'appstore config') {
|
|
179
|
-
if (!configArg || typeof configArg !== 'object') {
|
|
180
|
-
throw new Error(`Invalid ${labelArg}: config must be an object`);
|
|
181
|
-
}
|
|
182
|
-
if (!configArg.image || typeof configArg.image !== 'string') {
|
|
183
|
-
throw new Error(`Invalid ${labelArg}: image is required`);
|
|
184
|
-
}
|
|
185
|
-
if (configArg.port !== undefined) {
|
|
186
|
-
this.assertValidPort(configArg.port, `${labelArg} port`);
|
|
187
|
-
}
|
|
188
|
-
this.validateTargetPortModel(configArg, labelArg);
|
|
189
|
-
const containerArgErrors = interfaces.data.validateServiceContainerArgs(configArg.containerArgs);
|
|
190
|
-
if (containerArgErrors.length > 0) {
|
|
191
|
-
throw new Error(`Invalid ${labelArg}: ${containerArgErrors.join('; ')}`);
|
|
192
|
-
}
|
|
193
|
-
const environmentErrors = interfaces.appstore.validateAppStoreEnvironmentDeclarations(configArg.envVars);
|
|
194
|
-
if (environmentErrors.length > 0) {
|
|
195
|
-
throw new Error(`Invalid ${labelArg}: ${environmentErrors.join('; ')}`);
|
|
196
|
-
}
|
|
197
|
-
validateAppStoreStorageConfig(configArg, labelArg);
|
|
198
|
-
const platformOidcErrors = interfaces.appstore.validateAppStoreVersionPlatformOidc(configArg);
|
|
199
|
-
if (platformOidcErrors.length > 0) {
|
|
200
|
-
throw new Error(`Invalid ${labelArg}: ${platformOidcErrors.join('; ')}`);
|
|
201
|
-
}
|
|
202
|
-
this.validatePublishedPorts(configArg.publishedPorts || [], labelArg);
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Produces the canonical storage handoff only after target feature
|
|
206
|
-
* negotiation. Fulfillment adapters should use this method before creating
|
|
207
|
-
* or mutating any storage resource.
|
|
208
|
-
*/
|
|
209
|
-
normalizeStorageConfig(configArg, optionsArg, labelArg = 'appstore config') {
|
|
210
|
-
this.validateAppStoreVersionConfig(configArg, labelArg);
|
|
211
|
-
return normalizeAppStoreStorageConfig(configArg, optionsArg, labelArg);
|
|
212
|
-
}
|
|
213
|
-
normalizeVolumes(volumesArg = []) {
|
|
214
|
-
return volumesArg.map((volumeArg) => {
|
|
215
|
-
if (typeof volumeArg === 'string') {
|
|
216
|
-
return { mountPath: volumeArg };
|
|
217
|
-
}
|
|
218
|
-
return volumeArg;
|
|
219
|
-
}).map((volumeArg, indexArg) => {
|
|
220
|
-
this.validateVolume(volumeArg, `volume ${indexArg + 1}`);
|
|
221
|
-
return volumeArg;
|
|
222
|
-
});
|
|
223
|
-
}
|
|
224
|
-
async fetchAppStoreIndex() {
|
|
225
|
-
try {
|
|
226
|
-
return await this.fetchJson('appstore.resolved.json');
|
|
227
|
-
}
|
|
228
|
-
catch {
|
|
229
|
-
return await this.fetchJson('appstore.json');
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
async resolveAppStoreApp(appArg) {
|
|
233
|
-
if (appArg.source?.type === 'repoManifest') {
|
|
234
|
-
const resolvedApp = await this.resolveRepoManifestSource(appArg.source, appArg);
|
|
235
|
-
return {
|
|
236
|
-
...resolvedApp.appStoreApp,
|
|
237
|
-
...withoutUndefined(appArg),
|
|
238
|
-
latestVersion: resolvedApp.appStoreApp.latestVersion,
|
|
239
|
-
versions: resolvedApp.appStoreApp.versions,
|
|
240
|
-
source: appArg.source,
|
|
241
|
-
tags: appArg.tags || resolvedApp.appStoreApp.tags,
|
|
242
|
-
resolvedSource: resolvedApp.appStoreApp.resolvedSource,
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
if (appArg.source?.type === 'dockerImage') {
|
|
246
|
-
const config = appArg.runtime ? { ...appArg.runtime } : undefined;
|
|
247
|
-
const resolvedSource = config
|
|
248
|
-
? (await this.applyDockerImageSourceToConfig(appArg.source, config, appArg.latestVersion)).resolvedSource
|
|
249
|
-
: await this.resolveDockerImageSource(appArg.source);
|
|
250
|
-
const latestVersion = createAppStoreVersionForDockerSource(appArg.source, appArg.latestVersion, resolvedSource?.imageDigest);
|
|
251
|
-
return {
|
|
252
|
-
...appArg,
|
|
253
|
-
runtime: config,
|
|
254
|
-
latestVersion,
|
|
255
|
-
versions: uniqueStrings([...(appArg.versions || []), latestVersion]),
|
|
256
|
-
upgradeStrategy: appArg.source.tracking === 'digest' ? 'dockerDigest' : appArg.upgradeStrategy,
|
|
257
|
-
resolvedSource,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
const appMeta = await this.fetchJson(`apps/${appArg.id}/app.json`);
|
|
261
|
-
return this.validateInlineAppMetadata(appArg, appMeta);
|
|
262
|
-
}
|
|
263
|
-
async resolveServezoneAppStoreManifest(manifestArg, resolvedSourceArg) {
|
|
264
|
-
const configsByVersion = new Map();
|
|
265
|
-
const versions = [];
|
|
266
|
-
const sourceVersionToResolvedVersion = new Map();
|
|
267
|
-
for (const versionArg of manifestArg.versions || []) {
|
|
268
|
-
const sourceVersion = versionArg.version;
|
|
269
|
-
const { version: _version, ...versionConfig } = versionArg;
|
|
270
|
-
const config = {
|
|
271
|
-
...versionConfig,
|
|
272
|
-
source: versionConfig.source || manifestArg.source,
|
|
273
|
-
resolvedSource: resolvedSourceArg,
|
|
274
|
-
};
|
|
275
|
-
await this.resolveConfigSource(config, sourceVersion);
|
|
276
|
-
const resolvedVersion = config.appStoreVersion || sourceVersion;
|
|
277
|
-
config.appStoreVersion = resolvedVersion;
|
|
278
|
-
this.validateAppStoreVersionConfig(config, `${manifestArg.app.id}@${resolvedVersion}`);
|
|
279
|
-
configsByVersion.set(resolvedVersion, config);
|
|
280
|
-
configsByVersion.set(sourceVersion, config);
|
|
281
|
-
versions.push(resolvedVersion);
|
|
282
|
-
sourceVersionToResolvedVersion.set(sourceVersion, resolvedVersion);
|
|
283
|
-
}
|
|
284
|
-
if (manifestArg.runtime) {
|
|
285
|
-
const sourceVersion = manifestArg.latestVersion || manifestArg.channel || 'latest';
|
|
286
|
-
const config = {
|
|
287
|
-
...manifestArg.runtime,
|
|
288
|
-
source: manifestArg.runtime.source || manifestArg.source,
|
|
289
|
-
resolvedSource: resolvedSourceArg,
|
|
290
|
-
};
|
|
291
|
-
await this.resolveConfigSource(config, sourceVersion);
|
|
292
|
-
const resolvedVersion = config.appStoreVersion || sourceVersion;
|
|
293
|
-
config.appStoreVersion = resolvedVersion;
|
|
294
|
-
this.validateAppStoreVersionConfig(config, `${manifestArg.app.id}@${resolvedVersion}`);
|
|
295
|
-
configsByVersion.set(resolvedVersion, config);
|
|
296
|
-
configsByVersion.set(sourceVersion, config);
|
|
297
|
-
versions.push(resolvedVersion);
|
|
298
|
-
sourceVersionToResolvedVersion.set(sourceVersion, resolvedVersion);
|
|
299
|
-
}
|
|
300
|
-
if (configsByVersion.size === 0) {
|
|
301
|
-
throw new Error('Appstore manifest must define at least one runtime config or version');
|
|
302
|
-
}
|
|
303
|
-
const selectedChannel = manifestArg.policy?.defaultChannel || manifestArg.channel || 'stable';
|
|
304
|
-
const channelVersion = manifestArg.channels?.[selectedChannel];
|
|
305
|
-
const uniqueVersions = uniqueStrings(versions);
|
|
306
|
-
const declaredLatestVersion = manifestArg.latestVersion
|
|
307
|
-
|| channelVersion
|
|
308
|
-
|| selectImplicitLatestVersion(uniqueVersions, `Appstore manifest '${manifestArg.app.id}'`);
|
|
309
|
-
const latestVersion = sourceVersionToResolvedVersion.get(declaredLatestVersion)
|
|
310
|
-
|| declaredLatestVersion;
|
|
311
|
-
if (!configsByVersion.has(latestVersion)) {
|
|
312
|
-
throw new Error(`Appstore manifest '${manifestArg.app.id}' latestVersion '${declaredLatestVersion}' has no runtime config`);
|
|
313
|
-
}
|
|
314
|
-
const appStoreApp = {
|
|
315
|
-
id: manifestArg.app.id,
|
|
316
|
-
name: manifestArg.app.name,
|
|
317
|
-
description: manifestArg.app.description,
|
|
318
|
-
category: manifestArg.app.category,
|
|
319
|
-
iconName: manifestArg.app.iconName,
|
|
320
|
-
iconUrl: manifestArg.app.iconUrl,
|
|
321
|
-
latestVersion,
|
|
322
|
-
versions: uniqueVersions,
|
|
323
|
-
tags: manifestArg.app.tags,
|
|
324
|
-
channel: selectedChannel,
|
|
325
|
-
source: manifestArg.source,
|
|
326
|
-
upgradeStrategy: getUpgradeStrategyForConfig(configsByVersion.get(latestVersion)),
|
|
327
|
-
resolvedSource: resolvedSourceArg,
|
|
328
|
-
};
|
|
329
|
-
const appMeta = {
|
|
330
|
-
id: manifestArg.app.id,
|
|
331
|
-
name: manifestArg.app.name,
|
|
332
|
-
description: manifestArg.app.description,
|
|
333
|
-
category: manifestArg.app.category,
|
|
334
|
-
iconName: manifestArg.app.iconName,
|
|
335
|
-
latestVersion,
|
|
336
|
-
versions: uniqueVersions,
|
|
337
|
-
maintainer: manifestArg.app.maintainer,
|
|
338
|
-
links: manifestArg.app.links,
|
|
339
|
-
tags: manifestArg.app.tags,
|
|
340
|
-
source: manifestArg.source,
|
|
341
|
-
resolvedSource: resolvedSourceArg,
|
|
342
|
-
};
|
|
343
|
-
return { appStoreApp, appMeta, configsByVersion };
|
|
344
|
-
}
|
|
345
|
-
async resolveConfigSource(configArg, versionArg) {
|
|
346
|
-
if (configArg.source?.type === 'dockerImage') {
|
|
347
|
-
await this.applyDockerImageSourceToConfig(configArg.source, configArg, versionArg);
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
async applyDockerImageSourceToConfig(sourceArg, configArg, versionArg) {
|
|
351
|
-
configArg.image = sourceArg.image;
|
|
352
|
-
configArg.source = sourceArg;
|
|
353
|
-
const resolvedSource = await this.resolveDockerImageSource(sourceArg);
|
|
354
|
-
configArg.resolvedSource = resolvedSource;
|
|
355
|
-
configArg.resolvedImageDigest = resolvedSource.imageDigest;
|
|
356
|
-
configArg.upgradeStrategy = sourceArg.tracking === 'digest' ? 'dockerDigest' : configArg.upgradeStrategy;
|
|
357
|
-
configArg.appStoreVersion = createAppStoreVersionForDockerSource(sourceArg, versionArg, resolvedSource.imageDigest);
|
|
358
|
-
return configArg;
|
|
359
|
-
}
|
|
360
|
-
validateInlineAppMetadata(appArg, appMetaArg) {
|
|
361
|
-
if (appMetaArg.id !== appArg.id) {
|
|
362
|
-
throw new Error(`App Store metadata ID '${appMetaArg.id}' does not match index app '${appArg.id}'`);
|
|
363
|
-
}
|
|
364
|
-
if (!appMetaArg.latestVersion) {
|
|
365
|
-
throw new Error(`App Store metadata for '${appArg.id}' has no latestVersion`);
|
|
366
|
-
}
|
|
367
|
-
const versions = uniqueStrings(appMetaArg.versions?.length ? appMetaArg.versions : [appMetaArg.latestVersion]);
|
|
368
|
-
if (!versions.includes(appMetaArg.latestVersion)) {
|
|
369
|
-
throw new Error(`App Store metadata for '${appArg.id}' latestVersion '${appMetaArg.latestVersion}' is not declared in versions`);
|
|
370
|
-
}
|
|
371
|
-
const semverLatest = selectHighestSemanticVersion(versions);
|
|
372
|
-
if (semverLatest && semverLatest !== appMetaArg.latestVersion) {
|
|
373
|
-
throw new Error(`App Store metadata for '${appArg.id}' declares latestVersion '${appMetaArg.latestVersion}' but highest semantic version is '${semverLatest}'`);
|
|
374
|
-
}
|
|
375
|
-
const resolvedLatestVersion = semverLatest || appMetaArg.latestVersion;
|
|
376
|
-
if (appArg.latestVersion !== resolvedLatestVersion) {
|
|
377
|
-
throw new Error(`App Store index for '${appArg.id}' declares latestVersion '${appArg.latestVersion}' but app metadata resolves '${resolvedLatestVersion}'`);
|
|
378
|
-
}
|
|
379
|
-
this.inlineAppMetaCache.set(appArg.id, {
|
|
380
|
-
...appMetaArg,
|
|
381
|
-
latestVersion: resolvedLatestVersion,
|
|
382
|
-
versions,
|
|
383
|
-
});
|
|
384
|
-
return {
|
|
385
|
-
...appArg,
|
|
386
|
-
latestVersion: resolvedLatestVersion,
|
|
387
|
-
versions,
|
|
388
|
-
};
|
|
389
|
-
}
|
|
390
|
-
createAppMetaFromAppStoreApp(appArg) {
|
|
391
|
-
return {
|
|
392
|
-
id: appArg.id,
|
|
393
|
-
name: appArg.name,
|
|
394
|
-
description: appArg.description,
|
|
395
|
-
category: appArg.category,
|
|
396
|
-
iconName: appArg.iconName,
|
|
397
|
-
latestVersion: appArg.latestVersion,
|
|
398
|
-
versions: appArg.versions || [appArg.latestVersion],
|
|
399
|
-
tags: appArg.tags,
|
|
400
|
-
source: appArg.source,
|
|
401
|
-
resolvedSource: appArg.resolvedSource,
|
|
402
|
-
};
|
|
403
|
-
}
|
|
404
|
-
async getAppStoreApp(appIdArg) {
|
|
405
|
-
const appStore = await this.getAppStoreIndex();
|
|
406
|
-
return appStore.apps.find((appArg) => appArg.id === appIdArg);
|
|
407
|
-
}
|
|
408
|
-
async withRemoteResponse(urlArg, initArg, consumeArg) {
|
|
409
|
-
const controller = new AbortController();
|
|
410
|
-
const upstreamSignal = initArg.signal;
|
|
411
|
-
const forwardAbort = () => {
|
|
412
|
-
controller.abort(upstreamSignal?.reason);
|
|
413
|
-
};
|
|
414
|
-
if (upstreamSignal?.aborted) {
|
|
415
|
-
forwardAbort();
|
|
416
|
-
}
|
|
417
|
-
else {
|
|
418
|
-
upstreamSignal?.addEventListener('abort', forwardAbort, { once: true });
|
|
419
|
-
}
|
|
420
|
-
const timeout = setTimeout(() => {
|
|
421
|
-
controller.abort(new Error(`App Store request timed out after ${this.requestTimeoutMs}ms: ${urlArg}`));
|
|
422
|
-
}, this.requestTimeoutMs);
|
|
423
|
-
let response;
|
|
424
|
-
try {
|
|
425
|
-
response = await this.fetchRef(urlArg, {
|
|
426
|
-
...initArg,
|
|
427
|
-
signal: controller.signal,
|
|
428
|
-
});
|
|
429
|
-
return await consumeArg(response);
|
|
430
|
-
}
|
|
431
|
-
catch (error) {
|
|
432
|
-
if (controller.signal.aborted && controller.signal.reason instanceof Error) {
|
|
433
|
-
throw controller.signal.reason;
|
|
434
|
-
}
|
|
435
|
-
throw error;
|
|
436
|
-
}
|
|
437
|
-
finally {
|
|
438
|
-
clearTimeout(timeout);
|
|
439
|
-
upstreamSignal?.removeEventListener('abort', forwardAbort);
|
|
440
|
-
if (response?.body && !response.bodyUsed) {
|
|
441
|
-
void response.body.cancel().catch(() => { });
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
async fetchRemoteHeaders(urlArg, initArg = {}) {
|
|
446
|
-
return await this.withRemoteResponse(urlArg, initArg, (responseArg) => ({
|
|
447
|
-
status: responseArg.status,
|
|
448
|
-
ok: responseArg.ok,
|
|
449
|
-
headers: new Headers(responseArg.headers),
|
|
450
|
-
}));
|
|
451
|
-
}
|
|
452
|
-
async fetchJson(pathArg) {
|
|
453
|
-
if (this.source === 'package') {
|
|
454
|
-
const value = appStorePackageData.jsonFiles[pathArg];
|
|
455
|
-
if (value === undefined) {
|
|
456
|
-
throw new Error(`Packaged App Store file not found: ${pathArg}`);
|
|
457
|
-
}
|
|
458
|
-
return structuredClone(value);
|
|
459
|
-
}
|
|
460
|
-
const url = `${this.baseUrl}/${pathArg}`;
|
|
461
|
-
return await this.withRemoteResponse(url, {}, async (responseArg) => {
|
|
462
|
-
if (!responseArg.ok) {
|
|
463
|
-
throw new Error(`HTTP ${responseArg.status} for ${url}`);
|
|
464
|
-
}
|
|
465
|
-
return await responseArg.json();
|
|
466
|
-
});
|
|
467
|
-
}
|
|
468
|
-
async fetchText(pathArg) {
|
|
469
|
-
if (this.source === 'package') {
|
|
470
|
-
if (pathArg in appStorePackageData.textFiles) {
|
|
471
|
-
return appStorePackageData.textFiles[pathArg];
|
|
472
|
-
}
|
|
473
|
-
if (pathArg in appStorePackageData.jsonFiles) {
|
|
474
|
-
return JSON.stringify(appStorePackageData.jsonFiles[pathArg]);
|
|
475
|
-
}
|
|
476
|
-
throw new Error(`Packaged App Store file not found: ${pathArg}`);
|
|
477
|
-
}
|
|
478
|
-
const url = `${this.baseUrl}/${pathArg}`;
|
|
479
|
-
return await this.withRemoteResponse(url, {}, async (responseArg) => {
|
|
480
|
-
if (!responseArg.ok) {
|
|
481
|
-
throw new Error(`HTTP ${responseArg.status} for ${url}`);
|
|
482
|
-
}
|
|
483
|
-
return await responseArg.text();
|
|
484
|
-
});
|
|
485
|
-
}
|
|
486
|
-
async fetchTextFromUrl(urlArg) {
|
|
487
|
-
return await this.withRemoteResponse(urlArg, {}, async (responseArg) => {
|
|
488
|
-
if (!responseArg.ok) {
|
|
489
|
-
throw new Error(`HTTP ${responseArg.status} for ${urlArg}`);
|
|
490
|
-
}
|
|
491
|
-
return await responseArg.text();
|
|
492
|
-
});
|
|
493
|
-
}
|
|
494
|
-
async fetchDockerManifestDigest(imageArg) {
|
|
495
|
-
const manifestUrl = `https://${imageArg.registry}/v2/${imageArg.repository}/manifests/${imageArg.tag}`;
|
|
496
|
-
const headers = new Headers({
|
|
497
|
-
Accept: [
|
|
498
|
-
'application/vnd.docker.distribution.manifest.v2+json',
|
|
499
|
-
'application/vnd.oci.image.manifest.v1+json',
|
|
500
|
-
'application/vnd.docker.distribution.manifest.list.v2+json',
|
|
501
|
-
'application/vnd.oci.image.index.v1+json',
|
|
502
|
-
].join(', '),
|
|
503
|
-
});
|
|
504
|
-
let response = await this.fetchRemoteHeaders(manifestUrl, { method: 'HEAD', headers });
|
|
505
|
-
if (response.status === 401) {
|
|
506
|
-
const authHeader = response.headers.get('www-authenticate');
|
|
507
|
-
const token = authHeader ? await this.fetchDockerRegistryToken(authHeader, imageArg.repository) : null;
|
|
508
|
-
if (token) {
|
|
509
|
-
headers.set('Authorization', `Bearer ${token}`);
|
|
510
|
-
response = await this.fetchRemoteHeaders(manifestUrl, { method: 'HEAD', headers });
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
if (!response.ok || !response.headers.get('docker-content-digest')) {
|
|
514
|
-
response = await this.fetchRemoteHeaders(manifestUrl, { method: 'GET', headers });
|
|
515
|
-
}
|
|
516
|
-
if (!response.ok) {
|
|
517
|
-
throw new Error(`HTTP ${response.status} while resolving ${imageArg.repository}:${imageArg.tag}`);
|
|
518
|
-
}
|
|
519
|
-
return response.headers.get('docker-content-digest');
|
|
520
|
-
}
|
|
521
|
-
async fetchDockerRegistryToken(authHeaderArg, repositoryArg) {
|
|
522
|
-
const match = authHeaderArg.match(/^Bearer\s+(.+)$/i);
|
|
523
|
-
if (!match)
|
|
524
|
-
return null;
|
|
525
|
-
const authParams = new Map();
|
|
526
|
-
for (const partArg of match[1].match(/(?:[^,\"]+|\"[^\"]*\")+/g) || []) {
|
|
527
|
-
const [key, rawValue] = partArg.split('=');
|
|
528
|
-
if (!key || rawValue === undefined)
|
|
529
|
-
continue;
|
|
530
|
-
authParams.set(key.trim(), rawValue.trim().replace(/^\"|\"$/g, ''));
|
|
531
|
-
}
|
|
532
|
-
const realm = authParams.get('realm');
|
|
533
|
-
if (!realm)
|
|
534
|
-
return null;
|
|
535
|
-
const tokenUrl = new URL(realm);
|
|
536
|
-
const service = authParams.get('service');
|
|
537
|
-
const scope = authParams.get('scope') || `repository:${repositoryArg}:pull`;
|
|
538
|
-
if (service)
|
|
539
|
-
tokenUrl.searchParams.set('service', service);
|
|
540
|
-
tokenUrl.searchParams.set('scope', scope);
|
|
541
|
-
const tokenResponse = await this.withRemoteResponse(tokenUrl.toString(), {}, async (responseArg) => {
|
|
542
|
-
if (!responseArg.ok)
|
|
543
|
-
return null;
|
|
544
|
-
return await responseArg.json();
|
|
545
|
-
});
|
|
546
|
-
return tokenResponse?.token || tokenResponse?.access_token || null;
|
|
547
|
-
}
|
|
548
|
-
validateVolume(volumeArg, labelArg) {
|
|
549
|
-
const unknownKeys = Object.keys(volumeArg).filter((keyArg) => ![
|
|
550
|
-
'name',
|
|
551
|
-
'source',
|
|
552
|
-
'mountPath',
|
|
553
|
-
'driver',
|
|
554
|
-
'readOnly',
|
|
555
|
-
'backup',
|
|
556
|
-
'options',
|
|
557
|
-
].includes(keyArg));
|
|
558
|
-
if (unknownKeys.length > 0) {
|
|
559
|
-
throw new Error(`Invalid ${labelArg}: unknown field(s) ${unknownKeys.sort().join(', ')}`);
|
|
560
|
-
}
|
|
561
|
-
if (!volumeArg.mountPath
|
|
562
|
-
|| interfaces.data.normalizeServiceAbsolutePath(volumeArg.mountPath) !== volumeArg.mountPath
|
|
563
|
-
|| volumeArg.mountPath === '/') {
|
|
564
|
-
throw new Error(`Invalid ${labelArg}: mountPath must be a canonical non-root absolute path`);
|
|
565
|
-
}
|
|
566
|
-
if (volumeArg.source !== undefined
|
|
567
|
-
|| volumeArg.driver !== undefined
|
|
568
|
-
|| volumeArg.options !== undefined) {
|
|
569
|
-
throw new Error(`Invalid ${labelArg}: physical source, driver, and options fields are not portable`);
|
|
570
|
-
}
|
|
571
|
-
if (volumeArg.name !== undefined
|
|
572
|
-
&& !/^[a-z][a-z0-9-]{0,62}$/.test(volumeArg.name)) {
|
|
573
|
-
throw new Error(`Invalid ${labelArg}: name must be a stable lowercase identifier`);
|
|
574
|
-
}
|
|
575
|
-
}
|
|
576
|
-
validatePublishedPorts(publishedPortsArg = [], labelArg) {
|
|
577
|
-
const seenPublishedPorts = new Set();
|
|
578
|
-
for (const portArg of publishedPortsArg) {
|
|
579
|
-
const protocol = portArg.protocol || 'tcp';
|
|
580
|
-
const targetStart = portArg.targetPort;
|
|
581
|
-
const targetEnd = portArg.targetPortEnd || targetStart;
|
|
582
|
-
const publishedStart = portArg.publishedPort || targetStart;
|
|
583
|
-
const publishedEnd = portArg.publishedPortEnd || (publishedStart + (targetEnd - targetStart));
|
|
584
|
-
const hostIp = portArg.hostIp || '0.0.0.0';
|
|
585
|
-
if (!['tcp', 'udp'].includes(protocol)) {
|
|
586
|
-
throw new Error(`Invalid ${labelArg}: published port protocol '${protocol}' is not supported`);
|
|
587
|
-
}
|
|
588
|
-
this.assertValidPort(targetStart, `${labelArg} targetPort`);
|
|
589
|
-
this.assertValidPort(targetEnd, `${labelArg} targetPortEnd`);
|
|
590
|
-
this.assertValidPort(publishedStart, `${labelArg} publishedPort`);
|
|
591
|
-
this.assertValidPort(publishedEnd, `${labelArg} publishedPortEnd`);
|
|
592
|
-
if (targetEnd < targetStart || publishedEnd < publishedStart) {
|
|
593
|
-
throw new Error(`Invalid ${labelArg}: published port ranges must be ascending`);
|
|
594
|
-
}
|
|
595
|
-
if ((targetEnd - targetStart) !== (publishedEnd - publishedStart)) {
|
|
596
|
-
throw new Error(`Invalid ${labelArg}: target and published port ranges must have the same size`);
|
|
597
|
-
}
|
|
598
|
-
if ((targetEnd - targetStart) > 1000) {
|
|
599
|
-
throw new Error(`Invalid ${labelArg}: published port ranges may not exceed 1001 ports`);
|
|
600
|
-
}
|
|
601
|
-
for (let offset = 0; offset <= targetEnd - targetStart; offset++) {
|
|
602
|
-
const publishedPort = publishedStart + offset;
|
|
603
|
-
const publishedKey = `${hostIp}/${protocol}/${publishedPort}`;
|
|
604
|
-
const wildcardKey = `0.0.0.0/${protocol}/${publishedPort}`;
|
|
605
|
-
const conflictsWithWildcard = hostIp === '0.0.0.0'
|
|
606
|
-
? Array.from(seenPublishedPorts).some((keyArg) => keyArg.endsWith(`/${protocol}/${publishedPort}`))
|
|
607
|
-
: seenPublishedPorts.has(wildcardKey);
|
|
608
|
-
if (seenPublishedPorts.has(publishedKey) || conflictsWithWildcard) {
|
|
609
|
-
throw new Error(`Invalid ${labelArg}: duplicate published port ${hostIp}:${publishedPort}/${protocol}`);
|
|
610
|
-
}
|
|
611
|
-
seenPublishedPorts.add(publishedKey);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
validateTargetPortModel(configArg, labelArg) {
|
|
616
|
-
if (configArg.port === undefined
|
|
617
|
-
&& (!configArg.targetPorts || configArg.targetPorts.length === 0)) {
|
|
618
|
-
throw new Error(`Invalid ${labelArg}: either port or targetPorts is required`);
|
|
619
|
-
}
|
|
620
|
-
try {
|
|
621
|
-
interfaces.data.normalizeServicePortConfig({
|
|
622
|
-
name: labelArg,
|
|
623
|
-
ports: configArg.port !== undefined ? { web: configArg.port } : undefined,
|
|
624
|
-
targetPorts: configArg.targetPorts,
|
|
625
|
-
domains: configArg.domains,
|
|
626
|
-
publicPortMappings: configArg.publicPortMappings,
|
|
627
|
-
});
|
|
628
|
-
}
|
|
629
|
-
catch (error) {
|
|
630
|
-
throw new Error(`Invalid ${labelArg}: ${error.message}`);
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
assertValidPort(portArg, labelArg) {
|
|
634
|
-
if (!Number.isInteger(portArg) || portArg < 1 || portArg > 65535) {
|
|
635
|
-
throw new Error(`Invalid ${labelArg}: ${portArg}. Expected an integer port between 1 and 65535.`);
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
}
|
|
639
|
-
export function parseAppStoreIndex(inputArg) {
|
|
640
|
-
const appStore = inputArg;
|
|
641
|
-
if (!appStore || typeof appStore !== 'object' || !Array.isArray(appStore.apps)) {
|
|
642
|
-
throw new Error('Invalid appstore format');
|
|
643
|
-
}
|
|
644
|
-
return appStore;
|
|
645
|
-
}
|
|
646
|
-
export function parseServezoneAppStoreManifest(inputArg) {
|
|
647
|
-
const manifest = inputArg;
|
|
648
|
-
if (!manifest || typeof manifest !== 'object') {
|
|
649
|
-
throw new Error('Appstore manifest must be an object');
|
|
650
|
-
}
|
|
651
|
-
if (!manifest.app?.id || !manifest.app?.name) {
|
|
652
|
-
throw new Error('Appstore manifest app.id and app.name are required');
|
|
653
|
-
}
|
|
654
|
-
return manifest;
|
|
655
|
-
}
|
|
656
|
-
export function parseDockerImageReference(imageArg) {
|
|
657
|
-
const [imageWithoutDigest, digest] = imageArg.split('@');
|
|
658
|
-
const imageParts = imageWithoutDigest.split('/');
|
|
659
|
-
const firstPart = imageParts[0];
|
|
660
|
-
const hasExplicitRegistry = imageParts.length > 1
|
|
661
|
-
&& (firstPart.includes('.') || firstPart.includes(':') || firstPart === 'localhost');
|
|
662
|
-
const registry = hasExplicitRegistry ? firstPart : 'registry-1.docker.io';
|
|
663
|
-
const repositoryParts = hasExplicitRegistry ? imageParts.slice(1) : imageParts;
|
|
664
|
-
let repositoryWithTag = repositoryParts.join('/');
|
|
665
|
-
if (!repositoryWithTag) {
|
|
666
|
-
throw new Error(`Invalid Docker image reference '${imageArg}'`);
|
|
667
|
-
}
|
|
668
|
-
if (!hasExplicitRegistry && !repositoryWithTag.includes('/')) {
|
|
669
|
-
repositoryWithTag = `library/${repositoryWithTag}`;
|
|
670
|
-
}
|
|
671
|
-
const lastSlashIndex = repositoryWithTag.lastIndexOf('/');
|
|
672
|
-
const lastColonIndex = repositoryWithTag.lastIndexOf(':');
|
|
673
|
-
const hasTag = lastColonIndex > lastSlashIndex;
|
|
674
|
-
const repository = hasTag ? repositoryWithTag.slice(0, lastColonIndex) : repositoryWithTag;
|
|
675
|
-
const tag = hasTag ? repositoryWithTag.slice(lastColonIndex + 1) : 'latest';
|
|
676
|
-
return { registry, repository, tag, digest };
|
|
677
|
-
}
|
|
678
|
-
export function createAppStoreVersionForDockerSource(sourceArg, fallbackVersionArg, digestArg) {
|
|
679
|
-
if (sourceArg.tracking !== 'digest' || !digestArg) {
|
|
680
|
-
return fallbackVersionArg;
|
|
681
|
-
}
|
|
682
|
-
const parsedImage = parseDockerImageReference(sourceArg.image);
|
|
683
|
-
return `${parsedImage.tag}@${digestArg}`;
|
|
684
|
-
}
|
|
685
|
-
async function createSha256Hex(inputArg) {
|
|
686
|
-
const digest = await crypto.subtle.digest('SHA-256', new TextEncoder().encode(inputArg));
|
|
687
|
-
return Array.from(new Uint8Array(digest))
|
|
688
|
-
.map((byteArg) => byteArg.toString(16).padStart(2, '0'))
|
|
689
|
-
.join('');
|
|
690
|
-
}
|
|
691
|
-
function selectHighestSemanticVersion(versionsArg) {
|
|
692
|
-
if (versionsArg.length === 0)
|
|
693
|
-
return null;
|
|
694
|
-
const parsedVersions = [];
|
|
695
|
-
for (const versionArg of versionsArg) {
|
|
696
|
-
try {
|
|
697
|
-
parsedVersions.push(new SmartVersion(versionArg));
|
|
698
|
-
}
|
|
699
|
-
catch {
|
|
700
|
-
return null;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
let highestIndex = 0;
|
|
704
|
-
for (let index = 1; index < parsedVersions.length; index++) {
|
|
705
|
-
if (parsedVersions[index].greaterThan(parsedVersions[highestIndex])) {
|
|
706
|
-
highestIndex = index;
|
|
707
|
-
}
|
|
708
|
-
}
|
|
709
|
-
return versionsArg[highestIndex];
|
|
710
|
-
}
|
|
711
|
-
function selectImplicitLatestVersion(versionsArg, labelArg) {
|
|
712
|
-
if (versionsArg.length === 0) {
|
|
713
|
-
throw new Error(`${labelArg} defines no versions`);
|
|
714
|
-
}
|
|
715
|
-
if (versionsArg.length === 1)
|
|
716
|
-
return versionsArg[0];
|
|
717
|
-
const semverLatest = selectHighestSemanticVersion(versionsArg);
|
|
718
|
-
if (!semverLatest) {
|
|
719
|
-
throw new Error(`${labelArg} must declare latestVersion or a channel when multiple non-semver versions exist`);
|
|
720
|
-
}
|
|
721
|
-
return semverLatest;
|
|
722
|
-
}
|
|
723
|
-
function uniqueStrings(valuesArg) {
|
|
724
|
-
return Array.from(new Set(valuesArg.filter(Boolean)));
|
|
725
|
-
}
|
|
726
|
-
function withoutUndefined(objectArg) {
|
|
727
|
-
return Object.fromEntries(Object.entries(objectArg).filter(([, valueArg]) => valueArg !== undefined));
|
|
728
|
-
}
|
|
729
|
-
function getUpgradeStrategyForConfig(configArg) {
|
|
730
|
-
if (configArg?.upgradeStrategy)
|
|
731
|
-
return configArg.upgradeStrategy;
|
|
732
|
-
if (configArg?.source?.type === 'dockerImage' && configArg.source.tracking === 'digest')
|
|
733
|
-
return 'dockerDigest';
|
|
734
|
-
return undefined;
|
|
735
|
-
}
|
|
736
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hcHBzdG9yZXJlc29sdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfY2xpZW50L2NsYXNzZXMuYXBwc3RvcmVyZXNvbHZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssVUFBVSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLFdBQVcsTUFBTSxpQkFBaUIsQ0FBQyxPQUFPLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUNoRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRCxPQUFPLEVBQ0wsOEJBQThCLEVBQzlCLDZCQUE2QixHQUM5QixNQUFNLGNBQWMsQ0FBQztBQWtCdEIsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUc7SUFDckMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJO0lBQ3RCLE9BQU8sRUFBRSxXQUFXLENBQUMsT0FBTztDQUM3QixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsOERBQThELENBQUM7QUFFM0csTUFBTSxPQUFPLGdCQUFnQjtJQUNYLE9BQU8sQ0FBUztJQUNmLFFBQVEsQ0FBZTtJQUN2QixNQUFNLENBQXNCO0lBQzVCLG9CQUFvQixDQUFVO0lBQzlCLGdCQUFnQixDQUFTO0lBQ3pCLEdBQUcsQ0FBYTtJQUN6QixhQUFhLEdBQTBCLElBQUksQ0FBQztJQUM1QyxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsRUFBZ0QsQ0FBQztJQUM3RSxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7SUFFakUsWUFBWSxVQUFVLEdBQTZCLEVBQUU7UUFDbkQsSUFBSSxDQUFDLE1BQU0sR0FBRyxVQUFVLENBQUMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sSUFBSSxVQUFVLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxRQUFR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
|