feat(appstore): use shared resolver

This commit is contained in:
2026-05-25 03:10:18 +00:00
parent be53f179ab
commit a30260e336
16 changed files with 279 additions and 1087 deletions
-202
View File
@@ -1,202 +0,0 @@
/**
* App Store type definitions
*/
export interface ICatalog {
schemaVersion: number;
updatedAt: string;
apps: ICatalogApp[];
resolvedAt?: string;
}
export type TAppCatalogSourceType = 'inline' | 'repoManifest' | 'dockerImage';
export type TAppCatalogTrackingMode = 'tag' | 'digest';
export type TAppUpgradeStrategy = 'semver' | 'branch' | 'dockerDigest';
export interface IAppCatalogInlineSource {
type: 'inline';
}
export interface IAppCatalogRepoManifestSource {
type: 'repoManifest';
url: string;
ref?: string;
}
export interface IAppCatalogDockerImageSource {
type: 'dockerImage';
image: string;
tracking?: TAppCatalogTrackingMode;
}
export type TAppCatalogSource =
| IAppCatalogInlineSource
| IAppCatalogRepoManifestSource
| IAppCatalogDockerImageSource;
export interface IResolvedCatalogSource {
type: TAppCatalogSourceType;
url?: string;
ref?: string;
image?: string;
manifestHash?: string;
imageDigest?: string;
resolvedAt: string;
}
export interface ICatalogApp {
id: string;
name: string;
description: string;
category: string;
iconName?: string;
iconUrl?: string;
latestVersion: string;
versions?: string[];
tags?: string[];
source?: TAppCatalogSource;
runtime?: IAppVersionConfig;
channel?: string;
upgradeStrategy?: TAppUpgradeStrategy;
resolvedSource?: IResolvedCatalogSource;
}
export interface IAppCatalogVolume {
name?: string;
source?: string;
mountPath: string;
driver?: string;
readOnly?: boolean;
backup?: boolean;
options?: Record<string, string>;
}
export type TAppCatalogVolumeSpec = string | IAppCatalogVolume;
export interface IAppCatalogPublishedPort {
targetPort: number;
targetPortEnd?: number;
publishedPort?: number;
publishedPortEnd?: number;
protocol?: 'tcp' | 'udp';
hostIp?: string;
}
export interface IAppMeta {
id: string;
name: string;
description: string;
category: string;
iconName?: string;
latestVersion: string;
versions: string[];
maintainer?: string;
links?: Record<string, string>;
tags?: string[];
source?: TAppCatalogSource;
resolvedSource?: IResolvedCatalogSource;
}
export interface IAppVersionConfig {
image: string;
port: number;
envVars?: Array<{ key: string; value: string; description: string; required?: boolean }>;
volumes?: TAppCatalogVolumeSpec[];
publishedPorts?: IAppCatalogPublishedPort[];
platformRequirements?: {
mongodb?: boolean;
s3?: boolean;
clickhouse?: boolean;
redis?: boolean;
mariadb?: boolean;
};
minOneboxVersion?: string;
catalogVersion?: string;
upgradeStrategy?: TAppUpgradeStrategy;
source?: TAppCatalogSource;
resolvedSource?: IResolvedCatalogSource;
resolvedImageDigest?: string;
changelog?: string;
breaking?: boolean;
requiresManualReview?: boolean;
migrationRequired?: boolean;
backupBeforeUpgrade?: boolean;
requiresFeatures?: string[];
healthCheck?: {
path?: string;
port?: number;
expectedStatus?: number;
};
}
export interface IServezoneCatalogAppInfo {
id: string;
name: string;
description: string;
category: string;
iconName?: string;
iconUrl?: string;
tags?: string[];
maintainer?: string;
links?: Record<string, string>;
}
export interface IServezoneCatalogVersion extends IAppVersionConfig {
version: string;
}
export interface IServezoneCatalogManifest {
schemaVersion: number;
app: IServezoneCatalogAppInfo;
latestVersion?: string;
channel?: string;
channels?: Record<string, string>;
source?: TAppCatalogSource;
runtime?: IAppVersionConfig;
versions?: IServezoneCatalogVersion[];
policy?: {
allowMutableImage?: boolean;
defaultChannel?: string;
};
}
export interface IAppInstallOptions {
appId: string;
version?: string;
serviceName: string;
domain?: string;
port?: number;
publishedPorts?: IAppCatalogPublishedPort[];
envVars?: Record<string, string>;
autoDNS?: boolean;
}
export interface IMigrationContext {
service: {
name: string;
image: string;
envVars: Record<string, string>;
port: number;
};
fromVersion: string;
toVersion: string;
}
export interface IMigrationResult {
success: boolean;
envVars?: Record<string, string>;
image?: string;
imageDigest?: string;
port?: number;
volumes?: IAppCatalogVolume[];
publishedPorts?: IAppCatalogPublishedPort[];
warnings: string[];
}
export interface IUpgradeableService {
serviceName: string;
appTemplateId: string;
currentVersion: string;
latestVersion: string;
hasMigration: boolean;
}
+158 -750
View File
File diff suppressed because it is too large Load Diff
+4 -2
View File
@@ -9,7 +9,9 @@ import { Onebox } from './classes/onebox.ts';
import { OneboxDaemon } from './classes/daemon.ts';
import { OneboxSystemd } from './classes/systemd.ts';
import { OneboxUpdateManager } from './classes/update-manager.ts';
import type { IAppVersionConfig } from './classes/appstore-types.ts';
import type * as servezoneInterfaces from '@serve.zone/interfaces';
type IAppStoreVersionConfig = servezoneInterfaces.appstore.IAppStoreVersionConfig;
export async function runCli(): Promise<void> {
const args = Deno.args;
@@ -591,7 +593,7 @@ function parseEnvArgs(args: string[]): Record<string, string> {
}
function getAppStoreEnvVars(
configArg: IAppVersionConfig,
configArg: IAppStoreVersionConfig,
overridesArg: Record<string, string>,
): Record<string, string> {
const envVars: Record<string, string> = {};
+11 -17
View File
@@ -13,10 +13,9 @@ export class AppStoreHandler {
}
private registerHandlers(): void {
// Get app templates (catalog)
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAppTemplates>(
'getAppTemplates',
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAppStoreTemplates>(
'getAppStoreTemplates',
async (dataArg) => {
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const apps = await this.opsServerRef.oneboxRef.appStore.getApps();
@@ -25,10 +24,9 @@ export class AppStoreHandler {
),
);
// Get app config for a specific version
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAppConfig>(
'getAppConfig',
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetAppStoreConfig>(
'getAppStoreConfig',
async (dataArg) => {
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const config = await this.opsServerRef.oneboxRef.appStore.getAppVersionConfig(
@@ -42,8 +40,8 @@ export class AppStoreHandler {
);
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_InstallAppTemplate>(
'installAppTemplate',
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_InstallAppStoreApp>(
'installAppStoreApp',
async (dataArg) => {
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const service = await this.opsServerRef.oneboxRef.appStore.installApp(dataArg.install);
@@ -52,22 +50,20 @@ export class AppStoreHandler {
),
);
// Get services with available upgrades
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetUpgradeableServices>(
'getUpgradeableServices',
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_GetUpgradeableAppStoreServices>(
'getUpgradeableAppStoreServices',
async (dataArg) => {
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
const services = await this.opsServerRef.oneboxRef.appStore.getUpgradeableServices();
const services = await this.opsServerRef.oneboxRef.appStore.getUpgradeableAppStoreServices();
return { services };
},
),
);
// Upgrade a service to a new template version
this.typedrouter.addTypedHandler(
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpgradeService>(
'upgradeService',
new plugins.typedrequest.TypedHandler<interfaces.requests.IReq_UpgradeAppStoreService>(
'upgradeAppStoreService',
async (dataArg) => {
await requireAdminIdentity(this.opsServerRef.adminHandler, dataArg);
@@ -84,7 +80,6 @@ export class AppStoreHandler {
logger.info(`Upgrading service '${dataArg.serviceName}' from v${existingService.appTemplateVersion} to v${dataArg.targetVersion}`);
// Execute migration
const migrationResult = await this.opsServerRef.oneboxRef.appStore.executeMigration(
existingService,
existingService.appTemplateVersion,
@@ -97,7 +92,6 @@ export class AppStoreHandler {
);
}
// Apply the upgrade
const updatedService = await this.opsServerRef.oneboxRef.appStore.applyUpgrade(
dataArg.serviceName,
migrationResult,
+5
View File
@@ -82,6 +82,11 @@ export { smartguard, smartjwt };
import { ContainerArchive } from '@serve.zone/containerarchive';
export { ContainerArchive };
// serve.zone App Store contracts and resolver
import * as servezoneInterfaces from '@serve.zone/interfaces';
import * as servezoneAppstore from '@serve.zone/appstore';
export { servezoneInterfaces, servezoneAppstore };
// Node.js compat for streaming
import * as nodeFs from 'node:fs';
import * as nodeStream from 'node:stream';