@serve.zone/appstore 32.26.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 +72 -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} +6742 -6741
- 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 +16 -11
- package/readme.md +162 -93
- 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.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 -7432
|
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5hcHBzdG9yZXJlc29sdmVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHNfY2xpZW50L2NsYXNzZXMuYXBwc3RvcmVyZXNvbHZlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssVUFBVSxNQUFNLHdCQUF3QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUN4RCxPQUFPLFdBQVcsTUFBTSxpQkFBaUIsQ0FBQyxPQUFPLElBQUksRUFBRSxNQUFNLEVBQUUsQ0FBQztBQUNoRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUMxRCxPQUFPLEVBQ0wsOEJBQThCLEVBQzlCLDZCQUE2QixHQUM5QixNQUFNLGNBQWMsQ0FBQztBQWtCdEIsTUFBTSxDQUFDLE1BQU0sdUJBQXVCLEdBQUc7SUFDckMsSUFBSSxFQUFFLFdBQVcsQ0FBQyxJQUFJO0lBQ3RCLE9BQU8sRUFBRSxXQUFXLENBQUMsT0FBTztDQUM3QixDQUFDO0FBRUYsTUFBTSxDQUFDLE1BQU0sNEJBQTRCLEdBQUcsOERBQThELENBQUM7QUFFM0csTUFBTSxPQUFPLGdCQUFnQjtJQUNYLE9BQU8sQ0FBUztJQUNmLFFBQVEsQ0FBZTtJQUN2QixNQUFNLENBQXNCO0lBQzVCLG9CQUFvQixDQUFVO0lBQzlCLGdCQUFnQixDQUFTO0lBQ3pCLEdBQUcsQ0FBYTtJQUN6QixhQUFhLEdBQTBCLElBQUksQ0FBQztJQUM1QyxrQkFBa0IsR0FBRyxJQUFJLEdBQUcsRUFBZ0QsQ0FBQztJQUM3RSxjQUFjLEdBQUcsSUFBSSxHQUFHLEVBQWdDLENBQUM7SUFFakUsWUFBWSxhQUF1QyxFQUFFO1FBQ25ELElBQUksQ0FBQyxNQUFNLEdBQUcsVUFBVSxDQUFDLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxPQUFPLElBQUksVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFD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
|