feat: add native Adminer database access

This commit is contained in:
reaper
2026-08-22 04:26:37 -05:00
parent 92b1c98f36
commit 5a61c1c6ff
11 changed files with 163 additions and 26 deletions
+2 -2
View File
@@ -12,7 +12,7 @@ Each signed runtime bundle contains a `runtime.json` manifest plus versioned exe
Runtime archives are created from a staging directory with `npm run build:native-runtime -- <staging-directory> <output.tar.gz>`. The packager resolves every executable inside the staging root, calculates its SHA-256 checksum, writes the immutable `runtime.json`, excludes the build template, and creates the distributable archive. Dockside independently verifies those checksums before declaring a runtime available. Runtime archives are created from a staging directory with `npm run build:native-runtime -- <staging-directory> <output.tar.gz>`. The packager resolves every executable inside the staging root, calculates its SHA-256 checksum, writes the immutable `runtime.json`, excludes the build template, and creates the distributable archive. Dockside independently verifies those checksums before declaring a runtime available.
The first reproducible bundle target is Linux x64. Run `npm run build:native-linux-x64` on a Docker-capable build machine. Docker is used only to create the portable artifact; users of that artifact do not need Docker. The recipe pins PHP 8.5.9, nginx 1.30.4, MariaDB 11.8.8, and WP-CLI 2.12.0 with their runtime libraries, runs executable, PHP-extension, and database-initialization smoke checks outside the build container, and then invokes the normal checksum packager. The first reproducible bundle target is Linux x64. Run `npm run build:native-linux-x64` on a Docker-capable build machine. Docker is used only to create the portable artifact; users of that artifact do not need Docker. The recipe pins PHP 8.5.9, nginx 1.30.4, MariaDB 11.8.8, WP-CLI 2.12.0, and Adminer 6.0.1 with their runtime libraries, runs executable, PHP-extension, database-initialization, and PHP syntax smoke checks outside the build container, and then invokes the normal checksum packager.
Dockside can install a bundled runtime or a user-selected runtime archive from Settings. Installation rejects absolute and parent-traversing archive entries, rejects symbolic links, verifies the target platform and architecture, and verifies every declared executable checksum before atomically replacing an older runtime. Electron packages include matching archives from `dist/native-runtime` when they are present at packaging time. Dockside can install a bundled runtime or a user-selected runtime archive from Settings. Installation rejects absolute and parent-traversing archive entries, rejects symbolic links, verifies the target platform and architecture, and verifies every declared executable checksum before atomically replacing an older runtime. Electron packages include matching archives from `dist/native-runtime` when they are present at packaging time.
@@ -27,7 +27,7 @@ Every project receives reserved loopback ports, generated service configuration,
3. Linux x64 bundle with PHP 8.5, nginx, MariaDB 11.8, and WP-CLI. 3. Linux x64 bundle with PHP 8.5, nginx, MariaDB 11.8, and WP-CLI.
4. Native project lifecycle and single-site WordPress provisioning. 4. Native project lifecycle and single-site WordPress provisioning.
5. Native service logs, compressed snapshots, and database import/export. 5. Native service logs, compressed snapshots, and database import/export.
6. Native database administration. 6. Native database administration with loopback-only automatic login.
7. macOS arm64/x64 and Windows x64 bundles. 7. macOS arm64/x64 and Windows x64 bundles.
8. Additional PHP/database versions, Apache, Drupal, Node.js, and developer services. 8. Additional PHP/database versions, Apache, Drupal, Node.js, and developer services.
+3 -1
View File
@@ -4,7 +4,9 @@ RUN apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/m
nginx=1.30.4-r3 mariadb=11.8.8-r0 mariadb-client=11.8.8-r0 bash file pax-utils \ nginx=1.30.4-r3 mariadb=11.8.8-r0 mariadb-client=11.8.8-r0 bash file pax-utils \
&& mkdir -p /stage/root /stage/bin /stage/lib \ && mkdir -p /stage/root /stage/bin /stage/lib \
&& curl -fsSLo /tmp/wp-cli.phar https://github.com/wp-cli/wp-cli/releases/download/v2.12.0/wp-cli-2.12.0.phar \ && curl -fsSLo /tmp/wp-cli.phar https://github.com/wp-cli/wp-cli/releases/download/v2.12.0/wp-cli-2.12.0.phar \
&& echo 'ce34ddd838f7351d6759068d09793f26755463b4a4610a5a5c0a97b68220d85c /tmp/wp-cli.phar' | sha256sum -c - && echo 'ce34ddd838f7351d6759068d09793f26755463b4a4610a5a5c0a97b68220d85c /tmp/wp-cli.phar' | sha256sum -c - \
&& curl -fsSLo /tmp/adminer.php https://github.com/vrana/adminer/releases/download/v6.0.1/adminer-6.0.1-mysql-en.php \
&& echo 'aa1964047a7ce6e44b26db14dc16a942820c54034b417e6223884df6fa8e24a9 /tmp/adminer.php' | sha256sum -c -
RUN docker-php-ext-install -j2 mysqli pdo_mysql RUN docker-php-ext-install -j2 mysqli pdo_mysql
+3
View File
@@ -114,6 +114,8 @@ EOF
done done
cp /tmp/wp-cli.phar "$root/usr/local/bin/wp-cli.phar" cp /tmp/wp-cli.phar "$root/usr/local/bin/wp-cli.phar"
mkdir -p "$root/usr/share/aurora"
cp /tmp/adminer.php "$root/usr/share/aurora/adminer.php"
cat > "$stage/bin/wp" <<'EOF' cat > "$stage/bin/wp" <<'EOF'
#!/bin/sh #!/bin/sh
runtime_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) runtime_root=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
@@ -136,6 +138,7 @@ cat > "$stage/runtime.template.json" <<EOF
{ "id": "mariadb", "version": "$mariadb_version", "executable": "bin/mariadbd" }, { "id": "mariadb", "version": "$mariadb_version", "executable": "bin/mariadbd" },
{ "id": "mariadb-client", "version": "$mariadb_version", "executable": "bin/mariadb" }, { "id": "mariadb-client", "version": "$mariadb_version", "executable": "bin/mariadb" },
{ "id": "mariadb-dump", "version": "$mariadb_version", "executable": "bin/mariadb-dump" }, { "id": "mariadb-dump", "version": "$mariadb_version", "executable": "bin/mariadb-dump" },
{ "id": "adminer", "version": "6.0.1", "executable": "root/usr/share/aurora/adminer.php" },
{ "id": "wp-cli", "version": "2.12.0", "executable": "bin/wp" } { "id": "wp-cli", "version": "2.12.0", "executable": "bin/wp" }
] ]
} }
+9
View File
@@ -67,6 +67,15 @@ if (extensions.error || extensions.status !== 0)
throw extensions.error || new Error(`PHP database extensions failed: ${extensions.stderr}`) throw extensions.error || new Error(`PHP database extensions failed: ${extensions.stderr}`)
process.stdout.write('PHP mysqli and pdo_mysql extensions OK\n') process.stdout.write('PHP mysqli and pdo_mysql extensions OK\n')
const adminer = spawnSync(
join(root, 'bin/php'),
['-l', join(root, 'root/usr/share/aurora/adminer.php')],
{ encoding: 'utf8' }
)
if (adminer.error || adminer.status !== 0)
throw adminer.error || new Error(`Adminer PHP syntax check failed: ${adminer.stderr}`)
process.stdout.write('Adminer 6.0.1 PHP syntax OK\n')
const databaseDirectory = mkdtempSync(join(tmpdir(), 'aurora-native-mariadb-')) const databaseDirectory = mkdtempSync(join(tmpdir(), 'aurora-native-mariadb-'))
const temporaryDirectory = mkdtempSync(join(tmpdir(), 'aurora-native-mariadb-tmp-')) const temporaryDirectory = mkdtempSync(join(tmpdir(), 'aurora-native-mariadb-tmp-'))
try { try {
+9 -6
View File
@@ -116,8 +116,10 @@ async function assertNativeStack(
throw new Error('Installed native runtime does not provide MariaDB 11.8.') throw new Error('Installed native runtime does not provide MariaDB 11.8.')
if (!versions.has('nginx') || !versions.has('wp-cli')) if (!versions.has('nginx') || !versions.has('wp-cli'))
throw new Error('Installed native runtime is missing nginx or WP-CLI.') throw new Error('Installed native runtime is missing nginx or WP-CLI.')
if (stack.adminer !== false || stack.redis || stack.mailpit || stack.xdebug) if (stack.adminer !== false && !versions.has('adminer'))
throw new Error('Adminer, Redis, Mailpit, and Xdebug are not enabled for Aurora Native yet.') throw new Error('Installed native runtime does not provide Adminer.')
if (stack.redis || stack.mailpit || stack.xdebug)
throw new Error('Redis, Mailpit, and Xdebug are not enabled for Aurora Native yet.')
} }
async function loadRegistry(): Promise<Registry> { async function loadRegistry(): Promise<Registry> {
@@ -532,10 +534,11 @@ export async function describeProject(name: string): Promise<AuroraProjectDetail
firefox_trust_status: c.runtimeEngine === 'native' ? 'unknown' : await firefoxTrustStatus(), firefox_trust_status: c.runtimeEngine === 'native' ? 'unknown' : await firefoxTrustStatus(),
chromium_trust_status: c.runtimeEngine === 'native' ? 'unknown' : await chromiumTrustStatus(), chromium_trust_status: c.runtimeEngine === 'native' ? 'unknown' : await chromiumTrustStatus(),
module_metadata: moduleMetadata, module_metadata: moduleMetadata,
adminer_url: adminer_url: c.modules.includes('adminer')
c.runtimeEngine === 'container' && c.modules.includes('adminer') ? c.runtimeEngine === 'native'
? `https://adminer.${projectHost(c.name)}` ? `${urlSet.http}/__aurora/adminer/`
: undefined, : `https://adminer.${projectHost(c.name)}`
: undefined,
services, services,
xdebug_enabled: c.xdebug === true, xdebug_enabled: c.xdebug === true,
runtime_engine: c.runtimeEngine ?? 'container', runtime_engine: c.runtimeEngine ?? 'container',
+20
View File
@@ -7,6 +7,7 @@ import { promisify } from 'util'
import { describe, expect, it } from 'vitest' import { describe, expect, it } from 'vitest'
import { import {
renderMariaDbConfig, renderMariaDbConfig,
renderNativeAdminerBootstrap,
renderNginxConfig, renderNginxConfig,
renderPhpFpmConfig, renderPhpFpmConfig,
startNativeProject, startNativeProject,
@@ -54,6 +55,16 @@ describe('native project configuration', () => {
expect(config).toContain('port=41003') expect(config).toContain('port=41003')
expect(config).toContain('/.aurora/native/data/mariadb') expect(config).toContain('/.aurora/native/data/mariadb')
}) })
it('creates a loopback Adminer endpoint with project database credentials', () => {
expect(renderNginxConfig(project)).toContain('location = /__aurora/adminer/')
const bootstrap = renderNativeAdminerBootstrap({
...project,
installedRuntimeRoot: '/tmp/aurora-runtime'
})
expect(bootstrap).toContain("value = '127.0.0.1:41003'")
expect(bootstrap).toContain("username.value = 'db'")
expect(bootstrap).toContain('/tmp/aurora-runtime/root/usr/share/aurora/adminer.php')
})
}) })
it.runIf(Boolean(process.env.AURORA_NATIVE_SMOKE_ROOT))( it.runIf(Boolean(process.env.AURORA_NATIVE_SMOKE_ROOT))(
@@ -170,6 +181,15 @@ it.runIf(Boolean(process.env.AURORA_NATIVE_WORDPRESS_SMOKE_ROOT))(
{ cwd: root, env: process.env } { cwd: root, env: process.env }
) )
expect(restored.stdout.trim()).toBe('Aurora native smoke') expect(restored.stdout.trim()).toBe('Aurora native smoke')
const adminerResponse = await fetch(
`http://127.0.0.1:${definition.ports.http}/__aurora/adminer/`
)
const adminerHtml = await adminerResponse.text()
expect(adminerResponse.ok).toBe(true)
expect(adminerHtml).toContain('Adminer')
expect(adminerHtml).toContain("username.value = 'db'")
expect(adminerHtml).toContain("value = '127.0.0.1:")
} finally { } finally {
await stopNativeProject(definition) await stopNativeProject(definition)
} }
+41
View File
@@ -68,6 +68,22 @@ http {
server_name localhost; server_name localhost;
root "${quoteNginx(webroot)}"; root "${quoteNginx(webroot)}";
index index.php index.html; index index.php index.html;
location = /__aurora/adminer/ {
fastcgi_pass 127.0.0.1:${project.ports.php};
fastcgi_param SCRIPT_FILENAME "${quoteNginx(join(directory, 'adminer.php'))}";
fastcgi_param SCRIPT_NAME /__aurora/adminer/;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param SERVER_NAME $server_name;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param HTTP_HOST $http_host;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
}
location / { try_files $uri $uri/ /index.php?$query_string; } location / { try_files $uri $uri/ /index.php?$query_string; }
location ~ \\.php$ { location ~ \\.php$ {
fastcgi_pass 127.0.0.1:${project.ports.php}; fastcgi_pass 127.0.0.1:${project.ports.php};
@@ -92,6 +108,30 @@ http {
` `
} }
export function renderNativeAdminerBootstrap(project: NativeProjectDefinition): string {
const adminer = join(installedRoot(project), 'root', 'usr', 'share', 'aurora', 'adminer.php')
return `<?php
// Generated by Aurora Core. This endpoint binds only to the project's loopback server.
?>
<script>
addEventListener('DOMContentLoaded', () => {
const username = document.querySelector('input[name="auth[username]"]');
if (!username) return;
const form = username.form;
form.querySelector('input[name="auth[server]"]').value = '127.0.0.1:${project.ports.database}';
username.value = 'db';
form.querySelector('input[name="auth[password]"]').value = 'db';
form.querySelector('input[name="auth[db]"]').value = 'db';
const permanent = form.querySelector('input[name="auth[permanent]"]');
if (permanent) permanent.checked = true;
form.submit();
});
</script>
<?php
require '${adminer.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}';
`
}
export function renderMariaDbConfig( export function renderMariaDbConfig(
project: NativeProjectDefinition, project: NativeProjectDefinition,
installedRuntimeRoot = runtimeRoot() installedRuntimeRoot = runtimeRoot()
@@ -128,6 +168,7 @@ export async function provisionNativeProject(project: NativeProjectDefinition):
await Promise.all([ await Promise.all([
writeFile(join(directory, 'config', 'php-fpm.conf'), renderPhpFpmConfig(project)), writeFile(join(directory, 'config', 'php-fpm.conf'), renderPhpFpmConfig(project)),
writeFile(join(directory, 'config', 'nginx.conf'), renderNginxConfig(project)), writeFile(join(directory, 'config', 'nginx.conf'), renderNginxConfig(project)),
writeFile(join(directory, 'adminer.php'), renderNativeAdminerBootstrap(project)),
writeFile( writeFile(
join(directory, 'config', 'mariadb.cnf'), join(directory, 'config', 'mariadb.cnf'),
renderMariaDbConfig(project, installedRoot(project)) renderMariaDbConfig(project, installedRoot(project))
+4 -1
View File
@@ -15,12 +15,15 @@ const componentIds = new Set([
'nginx', 'nginx',
'apache', 'apache',
'mariadb', 'mariadb',
'mariadb-client',
'mariadb-dump',
'mysql', 'mysql',
'postgres', 'postgres',
'node', 'node',
'composer', 'composer',
'wp-cli', 'wp-cli',
'drush' 'drush',
'adminer'
]) ])
export function validateNativeRuntimeManifest(value: unknown): AuroraNativeRuntimeManifest { export function validateNativeRuntimeManifest(value: unknown): AuroraNativeRuntimeManifest {
+40 -9
View File
@@ -10,7 +10,8 @@ import type {
AuroraRuntimeUpdateStatus AuroraRuntimeUpdateStatus
} from '../shared/types' } from '../shared/types'
const catalogUrl = process.env.AURORA_RUNTIME_CATALOG_URL || 'https://auroradockside.com/runtime/catalog.json' const catalogUrl =
process.env.AURORA_RUNTIME_CATALOG_URL || 'https://auroradockside.com/runtime/catalog.json'
const publicKeyPem = process.env.AURORA_RUNTIME_CATALOG_PUBLIC_KEY const publicKeyPem = process.env.AURORA_RUNTIME_CATALOG_PUBLIC_KEY
function compareVersions(left: string, right: string): number { function compareVersions(left: string, right: string): number {
@@ -25,13 +26,31 @@ function compareVersions(left: string, right: string): number {
export function validateRuntimeCatalog(value: unknown): AuroraRuntimeCatalog { export function validateRuntimeCatalog(value: unknown): AuroraRuntimeCatalog {
if (!value || typeof value !== 'object') throw new Error('Runtime catalog must be an object.') if (!value || typeof value !== 'object') throw new Error('Runtime catalog must be an object.')
const catalog = value as Record<string, unknown> const catalog = value as Record<string, unknown>
if (catalog.schema !== 1 || typeof catalog.generatedAt !== 'string' || !Array.isArray(catalog.releases)) if (
catalog.schema !== 1 ||
typeof catalog.generatedAt !== 'string' ||
!Array.isArray(catalog.releases)
)
throw new Error('Unsupported runtime catalog.') throw new Error('Unsupported runtime catalog.')
const releases = catalog.releases.map((entry) => { const releases = catalog.releases.map((entry) => {
if (!entry || typeof entry !== 'object') throw new Error('Invalid runtime catalog release.') if (!entry || typeof entry !== 'object') throw new Error('Invalid runtime catalog release.')
const release = entry as Record<string, unknown> const release = entry as Record<string, unknown>
if ( if (
!['php', 'nginx', 'apache', 'mariadb', 'mysql', 'postgres', 'node', 'composer', 'wp-cli', 'drush'].includes(String(release.component)) || ![
'php',
'nginx',
'apache',
'mariadb',
'mariadb-client',
'mariadb-dump',
'mysql',
'postgres',
'node',
'composer',
'wp-cli',
'drush',
'adminer'
].includes(String(release.component)) ||
typeof release.version !== 'string' || typeof release.version !== 'string' ||
!['linux', 'darwin', 'win32'].includes(String(release.platform)) || !['linux', 'darwin', 'win32'].includes(String(release.platform)) ||
!['x64', 'arm64'].includes(String(release.arch)) || !['x64', 'arm64'].includes(String(release.arch)) ||
@@ -40,7 +59,8 @@ export function validateRuntimeCatalog(value: unknown): AuroraRuntimeCatalog {
!release.url.startsWith('https://') || !release.url.startsWith('https://') ||
typeof release.sha256 !== 'string' || typeof release.sha256 !== 'string' ||
!/^[a-f0-9]{64}$/i.test(release.sha256) !/^[a-f0-9]{64}$/i.test(release.sha256)
) throw new Error('Invalid runtime catalog release.') )
throw new Error('Invalid runtime catalog release.')
return release as unknown as AuroraRuntimeCatalogRelease return release as unknown as AuroraRuntimeCatalogRelease
}) })
return { schema: 1, generatedAt: catalog.generatedAt, releases } return { schema: 1, generatedAt: catalog.generatedAt, releases }
@@ -53,12 +73,20 @@ export function findRuntimeUpdates(
arch: string arch: string
): AuroraRuntimeUpdate[] { ): AuroraRuntimeUpdate[] {
return installed.flatMap((component) => { return installed.flatMap((component) => {
const candidates = catalog.releases.filter((release) => const candidates = catalog.releases.filter(
release.component === component.id && release.platform === platform && release.arch === arch (release) =>
release.component === component.id && release.platform === platform && release.arch === arch
) )
const latest = candidates.sort((a, b) => compareVersions(b.version, a.version))[0] const latest = candidates.sort((a, b) => compareVersions(b.version, a.version))[0]
return latest && compareVersions(latest.version, component.version) > 0 return latest && compareVersions(latest.version, component.version) > 0
? [{ component: component.id, installedVersion: component.version, availableVersion: latest.version, channel: latest.channel }] ? [
{
component: component.id,
installedVersion: component.version,
availableVersion: latest.version,
channel: latest.channel
}
]
: [] : []
}) })
} }
@@ -76,7 +104,8 @@ async function remoteCatalog(): Promise<AuroraRuntimeCatalog> {
fetch(catalogUrl, { signal: controller.signal }), fetch(catalogUrl, { signal: controller.signal }),
fetch(`${catalogUrl}.sig`, { signal: controller.signal }) fetch(`${catalogUrl}.sig`, { signal: controller.signal })
]) ])
if (!catalogResponse.ok || !signatureResponse.ok) throw new Error('Runtime catalog server is unavailable.') if (!catalogResponse.ok || !signatureResponse.ok)
throw new Error('Runtime catalog server is unavailable.')
const body = Buffer.from(await catalogResponse.arrayBuffer()) const body = Buffer.from(await catalogResponse.arrayBuffer())
const signature = Buffer.from((await signatureResponse.text()).trim(), 'base64') const signature = Buffer.from((await signatureResponse.text()).trim(), 'base64')
if (!verify(null, body, createPublicKey(publicKeyPem), signature)) if (!verify(null, body, createPublicKey(publicKeyPem), signature))
@@ -87,7 +116,9 @@ async function remoteCatalog(): Promise<AuroraRuntimeCatalog> {
} }
} }
export async function getRuntimeUpdates(installed: AuroraNativeRuntimeComponent[]): Promise<AuroraRuntimeUpdateStatus> { export async function getRuntimeUpdates(
installed: AuroraNativeRuntimeComponent[]
): Promise<AuroraRuntimeUpdateStatus> {
const cacheDirectory = join(app.getPath('userData'), 'runtime-catalog') const cacheDirectory = join(app.getPath('userData'), 'runtime-catalog')
const cachePath = join(cacheDirectory, 'catalog.json') const cachePath = join(cacheDirectory, 'catalog.json')
let source: AuroraRuntimeUpdateStatus['source'] = 'bundled' let source: AuroraRuntimeUpdateStatus['source'] = 'bundled'
@@ -79,7 +79,7 @@ export function CreateProjectModal({ onClose }: { onClose: () => void }): React.
setWebServer('nginx') setWebServer('nginx')
setDatabase('mariadb') setDatabase('mariadb')
setDatabaseVersion('11.8') setDatabaseVersion('11.8')
setAdminer(false) setAdminer(true)
setRedis(false) setRedis(false)
setMailpit(false) setMailpit(false)
setXdebug(false) setXdebug(false)
@@ -459,7 +459,7 @@ export function CreateProjectModal({ onClose }: { onClose: () => void }): React.
> >
<input <input
type="checkbox" type="checkbox"
disabled={runtimeEngine === 'native'} disabled={runtimeEngine === 'native' && label !== 'Adminer'}
checked={value as boolean} checked={value as boolean}
onChange={(e) => (setter as (v: boolean) => void)(e.target.checked)} onChange={(e) => (setter as (v: boolean) => void)(e.target.checked)}
/> />
+30 -5
View File
@@ -2,7 +2,20 @@ export type ProjectStatus = 'running' | 'stopped' | 'paused' | 'starting' | 'sto
export type AuroraRuntimeEngine = 'container' | 'native' export type AuroraRuntimeEngine = 'container' | 'native'
export interface AuroraNativeRuntimeComponent { export interface AuroraNativeRuntimeComponent {
id: 'php' | 'nginx' | 'apache' | 'mariadb' | 'mysql' | 'postgres' | 'node' | 'composer' | 'wp-cli' | 'drush' id:
| 'php'
| 'nginx'
| 'apache'
| 'mariadb'
| 'mariadb-client'
| 'mariadb-dump'
| 'mysql'
| 'postgres'
| 'node'
| 'composer'
| 'wp-cli'
| 'drush'
| 'adminer'
version: string version: string
executable: string executable: string
sha256: string sha256: string
@@ -18,8 +31,20 @@ export interface AuroraNativeRuntimeManifest {
export interface AuroraRuntimeStatus { export interface AuroraRuntimeStatus {
selectedEngine: AuroraRuntimeEngine selectedEngine: AuroraRuntimeEngine
container: { available: boolean; provider: 'docker' | 'podman' | null; version?: string; reason?: string } container: {
native: { available: boolean; platform: string; arch: string; runtimeVersion?: string; components: AuroraNativeRuntimeComponent[]; reason?: string } available: boolean
provider: 'docker' | 'podman' | null
version?: string
reason?: string
}
native: {
available: boolean
platform: string
arch: string
runtimeVersion?: string
components: AuroraNativeRuntimeComponent[]
reason?: string
}
} }
export type AuroraRuntimeComponentId = AuroraNativeRuntimeComponent['id'] export type AuroraRuntimeComponentId = AuroraNativeRuntimeComponent['id']
@@ -189,7 +214,6 @@ export interface AuroraSnapshot {
Created: string Created: string
} }
export type AuroraModuleCategory = 'application' | 'service' | 'tool' export type AuroraModuleCategory = 'application' | 'service' | 'tool'
export type AuroraModuleSettingType = 'boolean' | 'select' | 'text' | 'number' export type AuroraModuleSettingType = 'boolean' | 'select' | 'text' | 'number'
@@ -252,7 +276,8 @@ export interface AuroraModuleManifest {
} }
} }
export type AuroraModuleLifecycleHook = 'projectCreate' | 'projectStart' | 'projectRemove' | 'packageUninstall' | 'projectTool' export type AuroraModuleLifecycleHook =
'projectCreate' | 'projectStart' | 'projectRemove' | 'packageUninstall' | 'projectTool'
export interface AuroraModuleCommand { export interface AuroraModuleCommand {
command: string command: string