|
| 1 | +// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. |
| 2 | + |
| 3 | +import { Args, Command, Flags } from '@oclif/core'; |
| 4 | +import { loadConfig } from '../utils/config.js'; |
| 5 | +import { printHeader, printKV, printSuccess, printError, printStep } from '../utils/format.js'; |
| 6 | + |
| 7 | +export default class Publish extends Command { |
| 8 | + static override description = 'Publish package to ObjectStack server'; |
| 9 | + |
| 10 | + static override args = { |
| 11 | + config: Args.string({ description: 'Configuration file path', required: false }), |
| 12 | + }; |
| 13 | + |
| 14 | + static override flags = { |
| 15 | + server: Flags.string({ |
| 16 | + char: 's', |
| 17 | + description: 'Server URL', |
| 18 | + env: 'OBJECTSTACK_SERVER_URL', |
| 19 | + default: 'http://localhost:3000', |
| 20 | + }), |
| 21 | + token: Flags.string({ |
| 22 | + char: 't', |
| 23 | + description: 'Auth token', |
| 24 | + env: 'OBJECTSTACK_AUTH_TOKEN', |
| 25 | + }), |
| 26 | + }; |
| 27 | + |
| 28 | + async run(): Promise<void> { |
| 29 | + const { args, flags } = await this.parse(Publish); |
| 30 | + |
| 31 | + printHeader('Publish Package'); |
| 32 | + |
| 33 | + try { |
| 34 | + // 1. Load config |
| 35 | + printStep('Loading configuration...'); |
| 36 | + const { config, absolutePath } = await loadConfig(args.config); |
| 37 | + |
| 38 | + if (!config || !config.manifest) { |
| 39 | + printError('Invalid config: missing manifest'); |
| 40 | + this.exit(1); |
| 41 | + } |
| 42 | + |
| 43 | + const manifest = config.manifest; |
| 44 | + |
| 45 | + printSuccess(`Loaded: ${absolutePath}`); |
| 46 | + |
| 47 | + // 2. Collect metadata |
| 48 | + printStep('Collecting metadata...'); |
| 49 | + const metadata = { |
| 50 | + objects: config.objects || [], |
| 51 | + views: config.views || [], |
| 52 | + apps: config.apps || [], |
| 53 | + flows: config.flows || [], |
| 54 | + agents: config.agents || [], |
| 55 | + tools: config.tools || [], |
| 56 | + translations: config.translations || [], |
| 57 | + }; |
| 58 | + |
| 59 | + console.log(''); |
| 60 | + printKV(' Package', `${manifest.id}@${manifest.version}`); |
| 61 | + printKV(' Objects', metadata.objects.length.toString()); |
| 62 | + printKV(' Views', metadata.views.length.toString()); |
| 63 | + printKV(' Apps', metadata.apps.length.toString()); |
| 64 | + printKV(' Flows', metadata.flows.length.toString()); |
| 65 | + printKV(' Agents', metadata.agents.length.toString()); |
| 66 | + printKV(' Tools', metadata.tools.length.toString()); |
| 67 | + printKV(' Translations', metadata.translations.length.toString()); |
| 68 | + |
| 69 | + // 3. Publish to server |
| 70 | + const serverUrl = `${flags.server}/api/v1/packages`; |
| 71 | + printStep(`Publishing to ${serverUrl}...`); |
| 72 | + |
| 73 | + const response = await fetch(serverUrl, { |
| 74 | + method: 'POST', |
| 75 | + headers: { |
| 76 | + 'Content-Type': 'application/json', |
| 77 | + ...(flags.token && { 'Authorization': `Bearer ${flags.token}` }), |
| 78 | + }, |
| 79 | + body: JSON.stringify({ manifest, metadata }), |
| 80 | + }); |
| 81 | + |
| 82 | + if (!response.ok) { |
| 83 | + const error = await response.json(); |
| 84 | + printError(`Publish failed: ${error.error || response.statusText}`); |
| 85 | + this.exit(1); |
| 86 | + } |
| 87 | + |
| 88 | + const result = await response.json(); |
| 89 | + const size = (JSON.stringify(metadata).length / 1024).toFixed(2); |
| 90 | + |
| 91 | + console.log(''); |
| 92 | + printSuccess(result.message); |
| 93 | + printKV(' Size', `${size} KB`); |
| 94 | + printKV(' Server', flags.server); |
| 95 | + |
| 96 | + } catch (error) { |
| 97 | + printError((error as Error).message); |
| 98 | + this.exit(1); |
| 99 | + } |
| 100 | + } |
| 101 | +} |
0 commit comments