Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changeset/config.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -22,6 +22,7 @@
"@objectstack/plugin-msw",
"@objectstack/plugin-dev",
"@objectstack/plugin-security",
"@objectstack/plugin-setup",
"@objectstack/express",
"@objectstack/fastify",
"@objectstack/hono",
Expand Down
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

### Added
- **`@objectstack/plugin-setup` — Platform Setup App plugin** — New internal plugin
(`packages/plugins/plugin-setup`) that owns and finalizes the platform Setup App.
Ships four built-in Setup Areas (Administration, Platform, System, AI) as empty
skeletons. Other plugins contribute navigation items via the `setupNav` service
during their `init` phase. At `start`, SetupPlugin merges all contributions,
filters out empty areas, and registers the finalized Setup App as an internal
platform app. This establishes clear architectural separation: **spec** = protocol
only, **objectql** = data/query only, **plugins** = system feature and UI composition.

### Documentation
- **Unified API query syntax documentation with Spec canonical format** — Rewrote
`content/docs/protocol/objectql/query-syntax.mdx` and
Expand Down
2 changes: 2 additions & 0 deletions ROADMAP.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -53,6 +53,7 @@ the ecosystem for enterprise workloads.
| Authentication (better-auth) | ✅ | `@objectstack/plugin-auth` |
| Auth in MSW/Mock Mode | ✅ | `@objectstack/plugin-auth` + `@objectstack/runtime` |
| RBAC / RLS / FLS Security | ✅ | `@objectstack/plugin-security` |
| Platform Setup App | ✅ | `@objectstack/plugin-setup` |
| CLI (16 commands) | ✅ | `@objectstack/cli` |
| Dev Mode Plugin | ✅ | `@objectstack/plugin-dev` |
| Next.js Adapter | ✅ | `@objectstack/nextjs` |
Expand DownExpand Up@@ -900,6 +901,7 @@ Final polish and advanced features.
| `@objectstack/driver-memory` | 3.0.8 | ✅ | ✅ Stable | 9/10 |
| `@objectstack/plugin-auth` | 3.0.8 | ✅ | ✅ Stable | 9/10 |
| `@objectstack/plugin-security` | 3.0.8 | — | ✅ Stable | 9/10 |
| `@objectstack/plugin-setup` | 3.3.1 | ✅ | ✅ Stable | 8/10 |
| `@objectstack/plugin-dev` | 3.0.8 | — | ✅ Stable | 10/10 |
| `@objectstack/plugin-hono-server` | 3.0.8 | — | ✅ Stable | 9/10 |
| `@objectstack/plugin-msw` | 3.0.8 | — | ✅ Stable | 9/10 |
Expand Down
11 changes: 11 additions & 0 deletions packages/plugins/plugin-setup/CHANGELOG.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
# @objectstack/plugin-setup

## 3.3.1

### Added

- Initial release of the Setup Plugin.
- Defines the platform Setup App identity (name, label, icon, permissions, branding).
- Ships 4 built-in Setup Areas: Administration, Platform, System, AI.
- Provides `setupNav` service for contribution-based navigation composition.
- Auto-filters empty areas and supports custom area extensions.
Comment on lines +1 to +11

CopilotAIMar 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This package changelog format diverges from the repo’s Changesets-generated package CHANGELOGs (e.g. other plugins use the standard "Patch/Minor Changes" sections and dependency bump lines). Since release automation uses Changesets (pnpm run version / changeset version), this file is likely to be overwritten or become inconsistent. Consider generating/maintaining it via Changesets (and/or aligning the format with other packages/plugins/*/CHANGELOG.md files).

Copilot uses AI. Check for mistakes.
110 changes: 110 additions & 0 deletions packages/plugins/plugin-setup/README.md
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
# @objectstack/plugin-setup

Setup Plugin for ObjectStack — owns and composes the platform **Setup App** with area-based navigation.

## Overview

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:

- **Spec** → protocol schemas only
- **ObjectQL** → data engine only
- **plugin-setup** → owns the Setup App identity, areas, and navigation composition

## Features

- **Four Built-in Areas**: Administration, Platform, System, and AI — shipped as empty skeletons.
- **Contribution Model**: Any plugin can contribute navigation items to Setup areas via the `setupNav` service.
- **Area Filtering**: Empty areas are automatically filtered out at finalization.
- **Custom Areas**: Plugins can contribute to custom area IDs beyond the four built-in ones.
- **I18n Labels**: All labels use the `I18nLabel` union type for internationalization.

## Usage

### Register the Plugin

```typescript
import { ObjectKernel } from '@objectstack/core';
import { SetupPlugin } from '@objectstack/plugin-setup';

const kernel = new ObjectKernel({
plugins: [
new SetupPlugin(),
// ... other plugins
],
});
```

### Contribute Navigation from Another Plugin

```typescript
import type { Plugin, PluginContext } from '@objectstack/core';
import type { SetupNavService } from '@objectstack/plugin-setup';
import { SETUP_AREA_IDS } from '@objectstack/plugin-setup';

export class MyPlugin implements Plugin {
name = 'com.example.my-plugin';

async init(ctx: PluginContext) {
const setupNav = ctx.getService<SetupNavService>('setupNav');

setupNav.contribute({
areaId: SETUP_AREA_IDS.administration,
items: [
{ id: 'nav_users', type: 'object', label: 'Users', objectName: 'sys_user' },
{ id: 'nav_roles', type: 'object', label: 'Roles', objectName: 'sys_role' },
],
});
}
}
```

### Exported Components

```typescript
import {
SetupPlugin,
type SetupNavService,
SETUP_APP_DEFAULTS,
type SetupNavContribution,
SETUP_AREAS,
SETUP_AREA_IDS,
type SetupAreaId,
} from '@objectstack/plugin-setup';
```

## Built-in Setup Areas

| Area | ID | Icon | Order | Description |
|:-----|:---|:-----|:-----:|:------------|
| Administration | `area_administration` | shield | 10 | Users, roles, permissions, security |
| Platform | `area_platform` | layers | 20 | Objects, fields, layouts, automation |
| System | `area_system` | settings | 30 | Datasources, integrations, jobs, logs |
| AI | `area_ai` | brain | 40 | Agents, models, RAG pipelines |

## Architecture

```
┌──────────────────────────────────────────┐
│ SetupPlugin │
│ │
│ init(): │
│ → registers 'setupNav' service │
│ │
│ start(): │
│ → collects contributions │
│ → merges into area skeletons │
│ → filters empty areas │
│ → registers finalized Setup App │
│ │
└──────────────────────────────────────────┘
▲ ▲
│ contribute() │ contribute()
┌────┴────┐ ┌────┴────┐
│ plugin │ │ plugin │
│ auth │ │security │
└─────────┘ └─────────┘
```

## License

Apache-2.0 © ObjectStack
21 changes: 21 additions & 0 deletions packages/plugins/plugin-setup/objectstack.config.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import { defineStack } from '@objectstack/spec';

/**
* ObjectStack Configuration for plugin-setup
*
* This configuration defines the manifest for the platform Setup plugin.
* The Setup App itself is composed at runtime by collecting setupNav
* contributions from all registered plugins.
*/
export default defineStack({
manifest: {
id: 'com.objectstack.plugin-setup',
namespace: 'setup',
version: '3.3.1',
type: 'plugin',
name: 'Platform Setup Plugin',
description: 'Owns and composes the platform Setup App with area-based navigation contributed by other plugins',
},
});
28 changes: 28 additions & 0 deletions packages/plugins/plugin-setup/package.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
{
"name": "@objectstack/plugin-setup",
"version": "3.3.1",
"license": "Apache-2.0",
"description": "Setup Plugin for ObjectStack — Platform Setup App with area-based navigation composition",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.js"
}
},
"scripts": {
"build": "tsup --config ../../../tsup.config.ts",
"test": "vitest run"
},
"dependencies": {
"@objectstack/core": "workspace:*",
"@objectstack/spec": "workspace:*"
},
"devDependencies": {
"@types/node": "^25.5.0",
"typescript": "^6.0.2",
"vitest": "^4.1.2"
}
}
12 changes: 12 additions & 0 deletions packages/plugins/plugin-setup/src/index.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

/**
* @objectstack/plugin-setup
*
* Setup Plugin for ObjectStack — owns and composes the platform Setup App.
* Other plugins contribute navigation items via the `setupNav` service.
*/

export { SetupPlugin, type SetupNavService } from './setup-plugin.js';
export { SETUP_APP_DEFAULTS, type SetupNavContribution } from './setup-app.js';
export { SETUP_AREAS, SETUP_AREA_IDS, type SetupAreaId } from './setup-areas.js';
46 changes: 46 additions & 0 deletions packages/plugins/plugin-setup/src/setup-app.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import type { App, NavigationArea, NavigationItem } from '@objectstack/spec/ui';

/**
* Default Setup App definition.
*
* This is the base identity of the platform Setup application.
* At runtime the `SetupPlugin` clones this definition, injects
* the merged navigation areas contributed by other plugins,
* and registers the final app.
*/
export const SETUP_APP_DEFAULTS: Omit<App, 'areas'> & { areas: NavigationArea[] } = {
name: 'setup',
label: {
key: 'setup.app.label',
defaultValue: 'Setup',
},
description: {
key: 'setup.app.description',
defaultValue: 'Platform settings and administration',
},
icon: 'settings',
active: true,
isDefault: false,
branding: {
primaryColor: '#475569', // Slate-600 — neutral admin palette
},
requiredPermissions: ['setup.access'],
areas: [],
};
Comment on lines +13 to +31

CopilotAIMar 31, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SETUP_APP_DEFAULTS is typed as always having areas, but SetupPlugin conditionally sets areas to undefined at runtime when there are no contributions. Using the stricter { areas: NavigationArea[] } type here can mislead consumers into assuming areas is always present. Consider typing SETUP_APP_DEFAULTS as App (or Omit<App, 'areas'> & { areas?: NavigationArea[] }) to match the actual runtime shape.

Copilot uses AI. Check for mistakes.

/**
* Navigation contribution that a plugin registers via the
* `setupNav` service convention during kernel init.
*
* Each contribution targets a specific area by its ID and provides
* one or more navigation items (or groups) to merge into that area.
*/
export interface SetupNavContribution {
/** Target area ID (e.g. `area_administration`). */
areaId: string;

/** Navigation items to contribute to the target area. */
items: NavigationItem[];
}
88 changes: 88 additions & 0 deletions packages/plugins/plugin-setup/src/setup-areas.ts
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.

import type { NavigationArea } from '@objectstack/spec/ui';

/**
* Well-known Setup Area IDs.
*
* Every internal or third-party plugin that wants to contribute settings
* navigation uses one of these area IDs (or defines a custom one).
*/
export const SETUP_AREA_IDS = {
administration: 'area_administration',
platform: 'area_platform',
system: 'area_system',
ai: 'area_ai',
} as const;

export type SetupAreaId = (typeof SETUP_AREA_IDS)[keyof typeof SETUP_AREA_IDS];

/**
* Built-in Setup Areas — empty skeletons.
*
* These are the four default areas that ship with the platform.
* Other plugins contribute navigation items into these areas
* via the `setupNav` service convention during kernel init.
*
* At finalization time, empty areas (no contributed navigation items)
* are automatically filtered out so the Setup App only shows
* areas that actually have content.
*/
export const SETUP_AREAS: readonly NavigationArea[] = [
{
id: SETUP_AREA_IDS.administration,
label: {
key: 'setup.areas.administration',
defaultValue: 'Administration',
},
icon: 'shield',
order: 10,
description: {
key: 'setup.areas.administration.description',
defaultValue: 'User management, roles, permissions, and security settings',
},
navigation: [],
},
{
id: SETUP_AREA_IDS.platform,
label: {
key: 'setup.areas.platform',
defaultValue: 'Platform',
},
icon: 'layers',
order: 20,
description: {
key: 'setup.areas.platform.description',
defaultValue: 'Objects, fields, layouts, automation, and extensibility settings',
},
navigation: [],
},
{
id: SETUP_AREA_IDS.system,
label: {
key: 'setup.areas.system',
defaultValue: 'System',
},
icon: 'settings',
order: 30,
description: {
key: 'setup.areas.system.description',
defaultValue: 'Datasources, integrations, jobs, logs, and environment configuration',
},
navigation: [],
},
{
id: SETUP_AREA_IDS.ai,
label: {
key: 'setup.areas.ai',
defaultValue: 'AI',
},
icon: 'brain',
order: 40,
description: {
key: 'setup.areas.ai.description',
defaultValue: 'AI agents, model registry, RAG pipelines, and intelligence settings',
},
navigation: [],
},
] as const;
Loading
Loading