-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathplugin.zod.ts
More file actions
124 lines (98 loc) · 5.12 KB
/
plugin.zod.ts
File metadata and controls
124 lines (98 loc) · 5.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license.
import { z } from 'zod';
// Service method interfaces use z.function() instead of z.any() for type safety.
// Generic data fields use z.unknown() for type safety.
export const PluginContextSchema = z.object({
ql: z.object({
object: z.function().describe('Get object handle for method chaining'),
query: z.function().describe('Execute a query'),
}).passthrough().describe('ObjectQL Engine Interface'),
os: z.object({
getCurrentUser: z.function().describe('Get the current authenticated user'),
getConfig: z.function().describe('Get platform configuration'),
}).passthrough().describe('ObjectStack Kernel Interface'),
logger: z.object({
debug: z.function().describe('Log debug message'),
info: z.function().describe('Log info message'),
warn: z.function().describe('Log warning message'),
error: z.function().describe('Log error message'),
}).passthrough().describe('Logger Interface'),
storage: z.object({
get: z.function().describe('Get a value from storage'),
set: z.function().describe('Set a value in storage'),
delete: z.function().describe('Delete a value from storage'),
}).passthrough().describe('Storage Interface'),
i18n: z.object({
t: z.function().describe('Translate a key'),
getLocale: z.function().describe('Get current locale'),
}).passthrough().describe('Internationalization Interface'),
metadata: z.record(z.string(), z.unknown()),
events: z.record(z.string(), z.unknown()),
app: z.object({
router: z.object({
get: z.function().describe('Register GET route handler'),
post: z.function().describe('Register POST route handler'),
use: z.function().describe('Register middleware'),
}).passthrough()
}).passthrough().describe('App Framework Interface'),
drivers: z.object({
register: z.function().describe('Register a driver'),
}).passthrough().describe('Driver Registry'),
});
export type PluginContextData = z.infer<typeof PluginContextSchema>;
export type PluginContext = PluginContextData;
/**
* Upgrade Context Schema
*
* Provides version migration context to the `onUpgrade` lifecycle hook.
* Enables developers to write conditional migration logic based on
* the previous and new versions.
*/
export const UpgradeContextSchema = z.object({
/** Version before upgrade */
previousVersion: z.string().describe('Version before upgrade'),
/** Version after upgrade */
newVersion: z.string().describe('Version after upgrade'),
/** Whether this is a major version bump */
isMajorUpgrade: z.boolean().describe('Whether this is a major version bump'),
/** Metadata snapshot before upgrade (for migration logic) */
previousMetadata: z.record(z.string(), z.unknown()).optional()
.describe('Metadata snapshot before upgrade'),
}).describe('Version migration context for onUpgrade hook');
export type UpgradeContext = z.infer<typeof UpgradeContextSchema>;
export const PluginLifecycleSchema = z.object({
onInstall: z.function().optional().describe('Called when plugin is installed'),
onEnable: z.function().optional().describe('Called when plugin is enabled'),
onDisable: z.function().optional().describe('Called when plugin is disabled'),
onUninstall: z.function().optional().describe('Called when plugin is uninstalled'),
onUpgrade: z.function().optional().describe('Called when plugin is upgraded. Receives UpgradeContext with previousVersion, newVersion, and isMajorUpgrade'),
});
export type PluginLifecycleHooks = z.infer<typeof PluginLifecycleSchema>;
/**
* Shared Plugin Types
* These are the specialized plugin types common between Manifest (Package) and Plugin (Runtime).
*/
export const CORE_PLUGIN_TYPES = [
'ui', // Frontend: Serves static assets/SPA (e.g. Console, Studio)
'driver', // Connectivity: Database or Storage adapters (e.g. SQL, S3)
'server', // Protocol: HTTP/RPC Servers (e.g. Hono, GraphQL)
'app', // Business: Vertical Solution Bundle (Metadata + Logic)
'theme', // Appearance: UI Overrides & CSS Variables
'agent', // AI: Autonomous Agent & Tool Definitions
'objectql' // Core: ObjectQL Engine Data Provider
] as const;
export const PluginSchema = PluginLifecycleSchema.extend({
id: z.string().min(1).optional().describe('Unique Plugin ID (e.g. com.example.crm)'),
type: z.enum([
'standard', // Default: General purpose backend logic (Service, Hook, etc.)
...CORE_PLUGIN_TYPES
]).default('standard').optional().describe('Plugin Type categorization for runtime behavior'),
staticPath: z.string().optional().describe('Absolute path to static assets (Required for type="ui-plugin")'),
slug: z.string().regex(/^[a-z0-9-_]+$/).optional().describe('URL path segment (Required for type="ui-plugin")'),
default: z.boolean().optional().describe('Serve at root path (Only one "ui-plugin" can be default)'),
version: z.string().regex(/^\d+\.\d+\.\d+$/).optional().describe('Semantic Version'),
description: z.string().optional(),
author: z.string().optional(),
homepage: z.string().url().optional(),
});
export type PluginDefinition = z.infer<typeof PluginSchema>;