Skip to content

Commit cc52e5c

Browse files
authored
Merge pull request #998 from objectstack-ai/copilot/add-plugin-setup-for-platform-app
2 parents 5527fb9 + 6fffcda commit cc52e5c

14 files changed

Lines changed: 820 additions & 0 deletions

File tree

.changeset/config.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@objectstack/plugin-msw",
2323
"@objectstack/plugin-dev",
2424
"@objectstack/plugin-security",
25+
"@objectstack/plugin-setup",
2526
"@objectstack/express",
2627
"@objectstack/fastify",
2728
"@objectstack/hono",

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- **`@objectstack/plugin-setup` — Platform Setup App plugin** — New internal plugin
12+
(`packages/plugins/plugin-setup`) that owns and finalizes the platform Setup App.
13+
Ships four built-in Setup Areas (Administration, Platform, System, AI) as empty
14+
skeletons. Other plugins contribute navigation items via the `setupNav` service
15+
during their `init` phase. At `start`, SetupPlugin merges all contributions,
16+
filters out empty areas, and registers the finalized Setup App as an internal
17+
platform app. This establishes clear architectural separation: **spec** = protocol
18+
only, **objectql** = data/query only, **plugins** = system feature and UI composition.
19+
1020
### Documentation
1121
- **Unified API query syntax documentation with Spec canonical format** — Rewrote
1222
`content/docs/protocol/objectql/query-syntax.mdx` and

ROADMAP.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ the ecosystem for enterprise workloads.
5353
| Authentication (better-auth) || `@objectstack/plugin-auth` |
5454
| Auth in MSW/Mock Mode || `@objectstack/plugin-auth` + `@objectstack/runtime` |
5555
| RBAC / RLS / FLS Security || `@objectstack/plugin-security` |
56+
| Platform Setup App || `@objectstack/plugin-setup` |
5657
| CLI (16 commands) || `@objectstack/cli` |
5758
| Dev Mode Plugin || `@objectstack/plugin-dev` |
5859
| Next.js Adapter || `@objectstack/nextjs` |
@@ -900,6 +901,7 @@ Final polish and advanced features.
900901
| `@objectstack/driver-memory` | 3.0.8 || ✅ Stable | 9/10 |
901902
| `@objectstack/plugin-auth` | 3.0.8 || ✅ Stable | 9/10 |
902903
| `@objectstack/plugin-security` | 3.0.8 || ✅ Stable | 9/10 |
904+
| `@objectstack/plugin-setup` | 3.3.1 || ✅ Stable | 8/10 |
903905
| `@objectstack/plugin-dev` | 3.0.8 || ✅ Stable | 10/10 |
904906
| `@objectstack/plugin-hono-server` | 3.0.8 || ✅ Stable | 9/10 |
905907
| `@objectstack/plugin-msw` | 3.0.8 || ✅ Stable | 9/10 |
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# @objectstack/plugin-setup
2+
3+
## 3.3.1
4+
5+
### Added
6+
7+
- Initial release of the Setup Plugin.
8+
- Defines the platform Setup App identity (name, label, icon, permissions, branding).
9+
- Ships 4 built-in Setup Areas: Administration, Platform, System, AI.
10+
- Provides `setupNav` service for contribution-based navigation composition.
11+
- Auto-filters empty areas and supports custom area extensions.
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
# @objectstack/plugin-setup
2+
3+
Setup Plugin for ObjectStack — owns and composes the platform **Setup App** with area-based navigation.
4+
5+
## Overview
6+
7+
The Setup App is the central administration interface of the ObjectStack platform (equivalent to Salesforce Setup or ServiceNow System Administration). Rather than scattering setup definitions across `spec` and `objectql`, this plugin provides clear ownership:
8+
9+
- **Spec** → protocol schemas only
10+
- **ObjectQL** → data engine only
11+
- **plugin-setup** → owns the Setup App identity, areas, and navigation composition
12+
13+
## Features
14+
15+
- **Four Built-in Areas**: Administration, Platform, System, and AI — shipped as empty skeletons.
16+
- **Contribution Model**: Any plugin can contribute navigation items to Setup areas via the `setupNav` service.
17+
- **Area Filtering**: Empty areas are automatically filtered out at finalization.
18+
- **Custom Areas**: Plugins can contribute to custom area IDs beyond the four built-in ones.
19+
- **I18n Labels**: All labels use the `I18nLabel` union type for internationalization.
20+
21+
## Usage
22+
23+
### Register the Plugin
24+
25+
```typescript
26+
import { ObjectKernel } from '@objectstack/core';
27+
import { SetupPlugin } from '@objectstack/plugin-setup';
28+
29+
const kernel = new ObjectKernel({
30+
plugins: [
31+
new SetupPlugin(),
32+
// ... other plugins
33+
],
34+
});
35+
```
36+
37+
### Contribute Navigation from Another Plugin
38+
39+
```typescript
40+
import type { Plugin, PluginContext } from '@objectstack/core';
41+
import type { SetupNavService } from '@objectstack/plugin-setup';
42+
import { SETUP_AREA_IDS } from '@objectstack/plugin-setup';
43+
44+
export class MyPlugin implements Plugin {
45+
name = 'com.example.my-plugin';
46+
47+
async init(ctx: PluginContext) {
48+
const setupNav = ctx.getService<SetupNavService>('setupNav');
49+
50+
setupNav.contribute({
51+
areaId: SETUP_AREA_IDS.administration,
52+
items: [
53+
{ id: 'nav_users', type: 'object', label: 'Users', objectName: 'sys_user' },
54+
{ id: 'nav_roles', type: 'object', label: 'Roles', objectName: 'sys_role' },
55+
],
56+
});
57+
}
58+
}
59+
```
60+
61+
### Exported Components
62+
63+
```typescript
64+
import {
65+
SetupPlugin,
66+
type SetupNavService,
67+
SETUP_APP_DEFAULTS,
68+
type SetupNavContribution,
69+
SETUP_AREAS,
70+
SETUP_AREA_IDS,
71+
type SetupAreaId,
72+
} from '@objectstack/plugin-setup';
73+
```
74+
75+
## Built-in Setup Areas
76+
77+
| Area | ID | Icon | Order | Description |
78+
|:-----|:---|:-----|:-----:|:------------|
79+
| Administration | `area_administration` | shield | 10 | Users, roles, permissions, security |
80+
| Platform | `area_platform` | layers | 20 | Objects, fields, layouts, automation |
81+
| System | `area_system` | settings | 30 | Datasources, integrations, jobs, logs |
82+
| AI | `area_ai` | brain | 40 | Agents, models, RAG pipelines |
83+
84+
## Architecture
85+
86+
```
87+
┌──────────────────────────────────────────┐
88+
│ SetupPlugin │
89+
│ │
90+
│ init(): │
91+
│ → registers 'setupNav' service │
92+
│ │
93+
│ start(): │
94+
│ → collects contributions │
95+
│ → merges into area skeletons │
96+
│ → filters empty areas │
97+
│ → registers finalized Setup App │
98+
│ │
99+
└──────────────────────────────────────────┘
100+
▲ ▲
101+
│ contribute() │ contribute()
102+
┌────┴────┐ ┌────┴────┐
103+
│ plugin │ │ plugin │
104+
│ auth │ │security │
105+
└─────────┘ └─────────┘
106+
```
107+
108+
## License
109+
110+
Apache-2.0 © ObjectStack
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import { defineStack } from '@objectstack/spec';
4+
5+
/**
6+
* ObjectStack Configuration for plugin-setup
7+
*
8+
* This configuration defines the manifest for the platform Setup plugin.
9+
* The Setup App itself is composed at runtime by collecting setupNav
10+
* contributions from all registered plugins.
11+
*/
12+
export default defineStack({
13+
manifest: {
14+
id: 'com.objectstack.plugin-setup',
15+
namespace: 'setup',
16+
version: '3.3.1',
17+
type: 'plugin',
18+
name: 'Platform Setup Plugin',
19+
description: 'Owns and composes the platform Setup App with area-based navigation contributed by other plugins',
20+
},
21+
});
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "@objectstack/plugin-setup",
3+
"version": "3.3.1",
4+
"license": "Apache-2.0",
5+
"description": "Setup Plugin for ObjectStack — Platform Setup App with area-based navigation composition",
6+
"main": "dist/index.js",
7+
"types": "dist/index.d.ts",
8+
"exports": {
9+
".": {
10+
"types": "./dist/index.d.ts",
11+
"import": "./dist/index.mjs",
12+
"require": "./dist/index.js"
13+
}
14+
},
15+
"scripts": {
16+
"build": "tsup --config ../../../tsup.config.ts",
17+
"test": "vitest run"
18+
},
19+
"dependencies": {
20+
"@objectstack/core": "workspace:*",
21+
"@objectstack/spec": "workspace:*"
22+
},
23+
"devDependencies": {
24+
"@types/node": "^25.5.0",
25+
"typescript": "^6.0.2",
26+
"vitest": "^4.1.2"
27+
}
28+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
/**
4+
* @objectstack/plugin-setup
5+
*
6+
* Setup Plugin for ObjectStack — owns and composes the platform Setup App.
7+
* Other plugins contribute navigation items via the `setupNav` service.
8+
*/
9+
10+
export { SetupPlugin, type SetupNavService } from './setup-plugin.js';
11+
export { SETUP_APP_DEFAULTS, type SetupNavContribution } from './setup-app.js';
12+
export { SETUP_AREAS, SETUP_AREA_IDS, type SetupAreaId } from './setup-areas.js';
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import type { App, NavigationArea, NavigationItem } from '@objectstack/spec/ui';
4+
5+
/**
6+
* Default Setup App definition.
7+
*
8+
* This is the base identity of the platform Setup application.
9+
* At runtime the `SetupPlugin` clones this definition, injects
10+
* the merged navigation areas contributed by other plugins,
11+
* and registers the final app.
12+
*/
13+
export const SETUP_APP_DEFAULTS: Omit<App, 'areas'> & { areas: NavigationArea[] } = {
14+
name: 'setup',
15+
label: {
16+
key: 'setup.app.label',
17+
defaultValue: 'Setup',
18+
},
19+
description: {
20+
key: 'setup.app.description',
21+
defaultValue: 'Platform settings and administration',
22+
},
23+
icon: 'settings',
24+
active: true,
25+
isDefault: false,
26+
branding: {
27+
primaryColor: '#475569', // Slate-600 — neutral admin palette
28+
},
29+
requiredPermissions: ['setup.access'],
30+
areas: [],
31+
};
32+
33+
/**
34+
* Navigation contribution that a plugin registers via the
35+
* `setupNav` service convention during kernel init.
36+
*
37+
* Each contribution targets a specific area by its ID and provides
38+
* one or more navigation items (or groups) to merge into that area.
39+
*/
40+
export interface SetupNavContribution {
41+
/** Target area ID (e.g. `area_administration`). */
42+
areaId: string;
43+
44+
/** Navigation items to contribute to the target area. */
45+
items: NavigationItem[];
46+
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
2+
3+
import type { NavigationArea } from '@objectstack/spec/ui';
4+
5+
/**
6+
* Well-known Setup Area IDs.
7+
*
8+
* Every internal or third-party plugin that wants to contribute settings
9+
* navigation uses one of these area IDs (or defines a custom one).
10+
*/
11+
export const SETUP_AREA_IDS = {
12+
administration: 'area_administration',
13+
platform: 'area_platform',
14+
system: 'area_system',
15+
ai: 'area_ai',
16+
} as const;
17+
18+
export type SetupAreaId = (typeof SETUP_AREA_IDS)[keyof typeof SETUP_AREA_IDS];
19+
20+
/**
21+
* Built-in Setup Areas — empty skeletons.
22+
*
23+
* These are the four default areas that ship with the platform.
24+
* Other plugins contribute navigation items into these areas
25+
* via the `setupNav` service convention during kernel init.
26+
*
27+
* At finalization time, empty areas (no contributed navigation items)
28+
* are automatically filtered out so the Setup App only shows
29+
* areas that actually have content.
30+
*/
31+
export const SETUP_AREAS: readonly NavigationArea[] = [
32+
{
33+
id: SETUP_AREA_IDS.administration,
34+
label: {
35+
key: 'setup.areas.administration',
36+
defaultValue: 'Administration',
37+
},
38+
icon: 'shield',
39+
order: 10,
40+
description: {
41+
key: 'setup.areas.administration.description',
42+
defaultValue: 'User management, roles, permissions, and security settings',
43+
},
44+
navigation: [],
45+
},
46+
{
47+
id: SETUP_AREA_IDS.platform,
48+
label: {
49+
key: 'setup.areas.platform',
50+
defaultValue: 'Platform',
51+
},
52+
icon: 'layers',
53+
order: 20,
54+
description: {
55+
key: 'setup.areas.platform.description',
56+
defaultValue: 'Objects, fields, layouts, automation, and extensibility settings',
57+
},
58+
navigation: [],
59+
},
60+
{
61+
id: SETUP_AREA_IDS.system,
62+
label: {
63+
key: 'setup.areas.system',
64+
defaultValue: 'System',
65+
},
66+
icon: 'settings',
67+
order: 30,
68+
description: {
69+
key: 'setup.areas.system.description',
70+
defaultValue: 'Datasources, integrations, jobs, logs, and environment configuration',
71+
},
72+
navigation: [],
73+
},
74+
{
75+
id: SETUP_AREA_IDS.ai,
76+
label: {
77+
key: 'setup.areas.ai',
78+
defaultValue: 'AI',
79+
},
80+
icon: 'brain',
81+
order: 40,
82+
description: {
83+
key: 'setup.areas.ai.description',
84+
defaultValue: 'AI agents, model registry, RAG pipelines, and intelligence settings',
85+
},
86+
navigation: [],
87+
},
88+
] as const;

0 commit comments

Comments
 (0)