Skip to content

Commit 12f00d9

Browse files
authored
Merge branch 'main' of https://github.com/objectstack-ai/framework into claude/evaluate-ai-code-business-project
Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com>
2 parents 85e6272 + 1f54410 commit 12f00d9

File tree

13 files changed

+724
-170
lines changed

13 files changed

+724
-170
lines changed

apps/server/objectstack.config.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import { MetadataPlugin } from '@objectstack/metadata';
2222
import { AIServicePlugin } from '@objectstack/service-ai';
2323
import { AutomationServicePlugin } from '@objectstack/service-automation';
2424
import { AnalyticsServicePlugin } from '@objectstack/service-analytics';
25+
import { PackageServicePlugin } from '@objectstack/service-package';
2526
import CrmApp from '../../examples/app-crm/objectstack.config';
2627
import TodoApp from '../../examples/app-todo/objectstack.config';
2728
import BiPluginManifest from '../../examples/plugin-bi/objectstack.config';
@@ -73,6 +74,7 @@ export default defineStack({
7374
},
7475
new DriverPlugin(new InMemoryDriver(), 'memory'),
7576
new DriverPlugin(tursoDriver, 'turso'),
77+
new PackageServicePlugin(), // Package management service
7678
new AppPlugin(CrmApp),
7779
new AppPlugin(TodoApp),
7880
new AppPlugin(BiPluginManifest),

apps/server/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@objectstack/service-analytics": "workspace:*",
3636
"@objectstack/service-automation": "workspace:*",
3737
"@objectstack/service-feed": "workspace:*",
38+
"@objectstack/service-package": "workspace:*",
3839
"@objectstack/spec": "workspace:*",
3940
"hono": "^4.12.12",
4041
"pino": "^10.3.1",
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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

Comments
 (0)