create-windy 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -3
- package/dist/cli.js +8077 -3852
- package/package.json +3 -3
- package/template/.windy-template.json +2 -2
- package/template/README.md +25 -3
- package/template/_gitignore +4 -0
- package/template/apps/agent-server/tests/__init__.py +1 -0
- package/template/apps/agent-server/tests/openai_provider_test_support.py +131 -0
- package/template/apps/agent-server/tests/test_openai_provider.py +7 -123
- package/template/apps/server/src/auth/routes.test-support.ts +94 -0
- package/template/apps/server/src/auth/routes.test.ts +20 -88
- package/template/apps/server/src/index.ts +17 -34
- package/template/apps/server/src/mcp/adapter.test.ts +3 -2
- package/template/apps/server/src/mcp/adapter.ts +9 -9
- package/template/apps/server/src/mcp/routes.ts +4 -3
- package/template/apps/server/src/platform-http-runtime.ts +87 -0
- package/template/apps/server/src/system/drizzle-system-configs.ts +319 -0
- package/template/apps/server/src/system/drizzle-system.ts +35 -315
- package/template/apps/server/src/system/resource-routes.ts +270 -0
- package/template/apps/server/src/system/routes.ts +3 -269
- package/template/apps/web/src/pages/system/components/SystemResourceLoadError.vue +21 -0
- package/template/apps/web/src/pages/system/components/SystemResourceLoadError.webtest.ts +17 -0
- package/template/apps/web/src/pages/system/components/SystemResourcePage.vue +5 -10
- package/template/docs/architecture/mcp-business-capabilities.md +107 -0
- package/template/docs/development/custom-login-page.md +3 -3
- package/template/docs/platform/agent-runtime.md +5 -5
- package/template/docs/platform/agent-tools.md +4 -0
- package/template/packages/modules/package.json +1 -1
- package/template/packages/modules/src/composition-fixtures.test-support.ts +164 -0
- package/template/packages/modules/src/composition.test.ts +5 -158
- package/template/packages/modules/src/system-api-operational.ts +234 -0
- package/template/packages/modules/src/system-api-permissions.ts +8 -229
- package/template/packages/modules/src/system-module-tasks.ts +86 -0
- package/template/packages/modules/src/system-modules-access.test.ts +60 -0
- package/template/packages/modules/src/system-modules.test.ts +0 -53
- package/template/packages/modules/src/system-modules.ts +2 -84
- package/template/packages/shared/index.ts +1 -0
- package/template/packages/shared/package.json +1 -1
- package/template/packages/shared/src/mcp.test.ts +12 -0
- package/template/packages/shared/src/mcp.ts +7 -0
|
@@ -26,10 +26,7 @@ import { GovernedToolRegistry } from "./agent/tool-registry.js";
|
|
|
26
26
|
import { PlatformMcpAdapter } from "./mcp/adapter.js";
|
|
27
27
|
import { registerMcpRoutes } from "./mcp/routes.js";
|
|
28
28
|
// @windy-module system.agent end
|
|
29
|
-
import { registerAuthRoutes, registerAuthSessionRoute } from "./auth/routes.js";
|
|
30
29
|
import { createAuthRuntime } from "./auth/runtime.js";
|
|
31
|
-
import { createPlatformHttpApp } from "./http-app.js";
|
|
32
|
-
import { bootstrapAdminPassword } from "./auth/bootstrap-admin.js";
|
|
33
30
|
import { createServerPersistence } from "./persistence.js";
|
|
34
31
|
// @windy-module system.license begin
|
|
35
32
|
import { registerPlatformLicenseRoutes } from "./license/routes.js";
|
|
@@ -51,7 +48,6 @@ import { SchedulerWorker } from "./scheduler/worker.js";
|
|
|
51
48
|
// @windy-module system.settings begin
|
|
52
49
|
import { createPlatformSettingsRuntime } from "./settings/runtime.js";
|
|
53
50
|
// @windy-module system.settings end
|
|
54
|
-
import { registerProfileRoutes } from "./profile/routes.js";
|
|
55
51
|
// @windy-module system.notification begin
|
|
56
52
|
import { registerNotificationRoutes } from "./notification/routes.js";
|
|
57
53
|
// @windy-module system.notification end
|
|
@@ -76,11 +72,13 @@ import { createSearchHost } from "./search/host.js";
|
|
|
76
72
|
// @windy-module system.workflow begin
|
|
77
73
|
import { registerWorkflowRoutes } from "./workflow/routes.js";
|
|
78
74
|
// @windy-module system.workflow end
|
|
79
|
-
import {
|
|
80
|
-
createPlatformObservability,
|
|
81
|
-
logPlatformStartup,
|
|
82
|
-
} from "./observability/bootstrap.js";
|
|
83
75
|
import { bootstrapServerModules } from "./module-bootstrap.js";
|
|
76
|
+
import {
|
|
77
|
+
createHttpObservability,
|
|
78
|
+
createPlatformServerApp,
|
|
79
|
+
listenPlatformServer,
|
|
80
|
+
logServerStartup,
|
|
81
|
+
} from "./platform-http-runtime.js";
|
|
84
82
|
|
|
85
83
|
const logger = pino({ name: "windy-server" });
|
|
86
84
|
const platformConfig = loadPlatformConfig();
|
|
@@ -128,14 +126,7 @@ const runtime = createServerRuntime(process.env, {
|
|
|
128
126
|
auditWriter: persistence?.auditWriter,
|
|
129
127
|
// @windy-module system.audit end
|
|
130
128
|
});
|
|
131
|
-
const observability =
|
|
132
|
-
databaseCheck: persistence
|
|
133
|
-
? async () => void (await persistence.pool.query("select 1"))
|
|
134
|
-
: undefined,
|
|
135
|
-
databaseRequired: process.env.NODE_ENV === "production",
|
|
136
|
-
auditStatus: () => runtime.auditSink.status(),
|
|
137
|
-
logger,
|
|
138
|
-
});
|
|
129
|
+
const observability = createHttpObservability(runtime, persistence, logger);
|
|
139
130
|
// @windy-module system.license begin
|
|
140
131
|
platformLicenseRuntime.setAuditSink(runtime.auditSink);
|
|
141
132
|
// @windy-module system.license end
|
|
@@ -208,20 +199,17 @@ const schedulerWorker = new SchedulerWorker(
|
|
|
208
199
|
(result) => observability.metrics.observeSchedulerTick(result),
|
|
209
200
|
);
|
|
210
201
|
// @windy-module system.scheduler end
|
|
211
|
-
await
|
|
202
|
+
const app = await createPlatformServerApp({
|
|
203
|
+
runtime,
|
|
204
|
+
persistence,
|
|
205
|
+
platformConfig,
|
|
206
|
+
authRepository,
|
|
212
207
|
authService,
|
|
213
|
-
authRepository: persistence?.authRepository,
|
|
214
208
|
repositories: systemRepositories,
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
observability.register(app);
|
|
219
|
-
registerAuthSessionRoute(app);
|
|
220
|
-
registerAuthRoutes(app, authService, {
|
|
221
|
-
sessionCookieName: platformConfig.security.sessionCookieName,
|
|
222
|
-
secureCookie: process.env.NODE_ENV === "production",
|
|
209
|
+
features,
|
|
210
|
+
logger,
|
|
211
|
+
observability,
|
|
223
212
|
});
|
|
224
|
-
registerProfileRoutes(app, authRepository, runtime, features);
|
|
225
213
|
|
|
226
214
|
// @windy-module system.license begin
|
|
227
215
|
registerPlatformLicenseRoutes(app, platformLicenseRuntime);
|
|
@@ -354,13 +342,8 @@ validateInstalledRuntime({
|
|
|
354
342
|
hosts: moduleHosts,
|
|
355
343
|
});
|
|
356
344
|
|
|
357
|
-
const port =
|
|
358
|
-
app.listen(port);
|
|
345
|
+
const port = listenPlatformServer(app);
|
|
359
346
|
// @windy-module system.scheduler begin
|
|
360
347
|
schedulerWorker.start();
|
|
361
348
|
// @windy-module system.scheduler end
|
|
362
|
-
|
|
363
|
-
featureSync,
|
|
364
|
-
persistenceEnabled: Boolean(persistence),
|
|
365
|
-
port,
|
|
366
|
-
});
|
|
349
|
+
logServerStartup(logger, featureSync, Boolean(persistence), port);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { afterEach, describe, expect, test } from "bun:test";
|
|
2
2
|
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
|
|
3
3
|
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
|
|
4
|
+
import { MCP_API_PATH } from "@southwind-ai/shared";
|
|
4
5
|
import { createFoundationSnapshot, loadSystemModules } from "../foundation.js";
|
|
5
6
|
import { createServerRuntime } from "../runtime.js";
|
|
6
7
|
import { createSystemRepositories } from "../system/seed.js";
|
|
@@ -150,7 +151,7 @@ async function connectClient(
|
|
|
150
151
|
token: string,
|
|
151
152
|
): Promise<Client> {
|
|
152
153
|
const transport = new StreamableHTTPClientTransport(
|
|
153
|
-
new URL(
|
|
154
|
+
new URL(`http://localhost${MCP_API_PATH}`),
|
|
154
155
|
{
|
|
155
156
|
requestInit: {
|
|
156
157
|
headers: { authorization: `Bearer ${token}` },
|
|
@@ -175,7 +176,7 @@ function mcpRequest(token?: string, origin?: string): Request {
|
|
|
175
176
|
});
|
|
176
177
|
if (token) headers.set("authorization", `Bearer ${token}`);
|
|
177
178
|
if (origin) headers.set("origin", origin);
|
|
178
|
-
return new Request(
|
|
179
|
+
return new Request(`http://localhost${MCP_API_PATH}`, {
|
|
179
180
|
method: "POST",
|
|
180
181
|
headers,
|
|
181
182
|
body: JSON.stringify({
|
|
@@ -10,7 +10,10 @@ import type {
|
|
|
10
10
|
ModuleToolInput,
|
|
11
11
|
ModuleToolResult,
|
|
12
12
|
} from "@southwind-ai/server-sdk";
|
|
13
|
-
import
|
|
13
|
+
import {
|
|
14
|
+
MCP_SERVER_INFO,
|
|
15
|
+
type FeatureFlagDefinition,
|
|
16
|
+
} from "@southwind-ai/shared";
|
|
14
17
|
import { evaluateAccessGuards } from "../access-guards.js";
|
|
15
18
|
import type { RequestGuardContext } from "../guards.js";
|
|
16
19
|
import { findFeature } from "../route-guards.js";
|
|
@@ -69,14 +72,11 @@ export class PlatformMcpAdapter {
|
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
private createServer(context: RequestGuardContext): Server {
|
|
72
|
-
const server = new Server(
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
"仅调用当前账号可见的只读业务工具;权限和数据范围由 Windy 平台逐次校验。",
|
|
78
|
-
},
|
|
79
|
-
);
|
|
75
|
+
const server = new Server(MCP_SERVER_INFO, {
|
|
76
|
+
capabilities: { tools: {} },
|
|
77
|
+
instructions:
|
|
78
|
+
"仅调用当前账号可见的只读业务工具;权限和数据范围由 Windy 平台逐次校验。",
|
|
79
|
+
});
|
|
80
80
|
|
|
81
81
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
82
82
|
tools: await this.allowedQueryTools(context),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MCP_ROUTE_PATH } from "@southwind-ai/shared";
|
|
1
2
|
import type { RouteApp } from "../system/routes.js";
|
|
2
3
|
import { PlatformMcpAdapter } from "./adapter.js";
|
|
3
4
|
|
|
@@ -15,7 +16,7 @@ export function registerMcpRoutes(
|
|
|
15
16
|
const context = rawContext as McpRouteContext;
|
|
16
17
|
return adapter.handle(context.request, context.guardContext, context.body);
|
|
17
18
|
};
|
|
18
|
-
app.get(
|
|
19
|
-
app.post(
|
|
20
|
-
app.delete(
|
|
19
|
+
app.get(MCP_ROUTE_PATH, handle);
|
|
20
|
+
app.post(MCP_ROUTE_PATH, handle);
|
|
21
|
+
app.delete(MCP_ROUTE_PATH, handle);
|
|
21
22
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { PlatformConfig } from "@southwind-ai/config";
|
|
2
|
+
import type { FeatureFlagDefinition } from "@southwind-ai/shared";
|
|
3
|
+
import type { AuthRepository } from "./auth/repository.js";
|
|
4
|
+
import type { AuthService } from "./auth/service.js";
|
|
5
|
+
import { bootstrapAdminPassword } from "./auth/bootstrap-admin.js";
|
|
6
|
+
import { registerAuthRoutes, registerAuthSessionRoute } from "./auth/routes.js";
|
|
7
|
+
import { createPlatformHttpApp } from "./http-app.js";
|
|
8
|
+
import {
|
|
9
|
+
createPlatformObservability,
|
|
10
|
+
logPlatformStartup,
|
|
11
|
+
} from "./observability/bootstrap.js";
|
|
12
|
+
import type { StructuredRequestLogger } from "./observability/http-observability.js";
|
|
13
|
+
import type { createServerPersistence } from "./persistence.js";
|
|
14
|
+
import { registerProfileRoutes } from "./profile/routes.js";
|
|
15
|
+
import type { createServerRuntime } from "./runtime.js";
|
|
16
|
+
import type { SystemRepositories } from "./system/seed.js";
|
|
17
|
+
import type { FeatureManifestSyncResult } from "./feature/manifest-feature-repository.js";
|
|
18
|
+
|
|
19
|
+
interface CreatePlatformServerAppInput {
|
|
20
|
+
runtime: ReturnType<typeof createServerRuntime>;
|
|
21
|
+
persistence: ReturnType<typeof createServerPersistence>;
|
|
22
|
+
platformConfig: PlatformConfig;
|
|
23
|
+
authRepository: AuthRepository;
|
|
24
|
+
authService: AuthService;
|
|
25
|
+
repositories: SystemRepositories;
|
|
26
|
+
features: FeatureFlagDefinition[];
|
|
27
|
+
logger: StructuredRequestLogger;
|
|
28
|
+
observability: ReturnType<typeof createPlatformObservability>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function createHttpObservability(
|
|
32
|
+
runtime: ReturnType<typeof createServerRuntime>,
|
|
33
|
+
persistence: ReturnType<typeof createServerPersistence>,
|
|
34
|
+
logger: StructuredRequestLogger,
|
|
35
|
+
) {
|
|
36
|
+
const database = persistence;
|
|
37
|
+
return createPlatformObservability({
|
|
38
|
+
databaseCheck: database
|
|
39
|
+
? async () => void (await database.pool.query("select 1"))
|
|
40
|
+
: undefined,
|
|
41
|
+
databaseRequired: process.env.NODE_ENV === "production",
|
|
42
|
+
auditStatus: () => runtime.auditSink.status(),
|
|
43
|
+
logger,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export async function createPlatformServerApp(
|
|
48
|
+
input: CreatePlatformServerAppInput,
|
|
49
|
+
) {
|
|
50
|
+
await bootstrapAdminPassword({
|
|
51
|
+
authService: input.authService,
|
|
52
|
+
authRepository: input.persistence?.authRepository,
|
|
53
|
+
repositories: input.repositories,
|
|
54
|
+
password: process.env.WINDY_BOOTSTRAP_ADMIN_PASSWORD,
|
|
55
|
+
});
|
|
56
|
+
const app = createPlatformHttpApp(input.runtime, input.observability);
|
|
57
|
+
input.observability.register(app);
|
|
58
|
+
registerAuthSessionRoute(app);
|
|
59
|
+
registerAuthRoutes(app, input.authService, {
|
|
60
|
+
sessionCookieName: input.platformConfig.security.sessionCookieName,
|
|
61
|
+
secureCookie: process.env.NODE_ENV === "production",
|
|
62
|
+
});
|
|
63
|
+
registerProfileRoutes(
|
|
64
|
+
app,
|
|
65
|
+
input.authRepository,
|
|
66
|
+
input.runtime,
|
|
67
|
+
input.features,
|
|
68
|
+
);
|
|
69
|
+
return app;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function listenPlatformServer(
|
|
73
|
+
app: ReturnType<typeof createPlatformHttpApp>,
|
|
74
|
+
): number {
|
|
75
|
+
const port = process.env.PORT ? Number(process.env.PORT) : 9_747;
|
|
76
|
+
app.listen(port);
|
|
77
|
+
return port;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function logServerStartup(
|
|
81
|
+
logger: StructuredRequestLogger,
|
|
82
|
+
featureSync: FeatureManifestSyncResult,
|
|
83
|
+
persistenceEnabled: boolean,
|
|
84
|
+
port: number,
|
|
85
|
+
): void {
|
|
86
|
+
logPlatformStartup(logger, { featureSync, persistenceEnabled, port });
|
|
87
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import {
|
|
2
|
+
departments,
|
|
3
|
+
dictionaries,
|
|
4
|
+
featureFlags,
|
|
5
|
+
// @windy-module system.license begin
|
|
6
|
+
legacyLicenses,
|
|
7
|
+
// @windy-module system.license end
|
|
8
|
+
menus,
|
|
9
|
+
roles,
|
|
10
|
+
users,
|
|
11
|
+
} from "@southwind-ai/database";
|
|
12
|
+
import type { NodePgDatabase } from "drizzle-orm/node-postgres";
|
|
13
|
+
import type {
|
|
14
|
+
ManagedDepartment,
|
|
15
|
+
ManagedDictionary,
|
|
16
|
+
ManagedFeature,
|
|
17
|
+
// @windy-module system.license begin
|
|
18
|
+
ManagedLicense,
|
|
19
|
+
// @windy-module system.license end
|
|
20
|
+
ManagedMenu,
|
|
21
|
+
ManagedRole,
|
|
22
|
+
ManagedUser,
|
|
23
|
+
} from "./entities.js";
|
|
24
|
+
import {
|
|
25
|
+
array,
|
|
26
|
+
auditEntity,
|
|
27
|
+
auditRow,
|
|
28
|
+
// @windy-module system.license begin
|
|
29
|
+
date,
|
|
30
|
+
iso,
|
|
31
|
+
optionalIso,
|
|
32
|
+
// @windy-module system.license end
|
|
33
|
+
pick,
|
|
34
|
+
} from "./drizzle-mapping.js";
|
|
35
|
+
import {
|
|
36
|
+
DrizzleEntityRepository,
|
|
37
|
+
type DrizzleEntityRepositoryConfig,
|
|
38
|
+
} from "./drizzle-repository.js";
|
|
39
|
+
import type { DrizzleScopedEntityRepositoryConfig } from "./drizzle-scoped-repository.js";
|
|
40
|
+
import type { DrizzleTransactionContext } from "./drizzle-transaction-context.js";
|
|
41
|
+
import { userDataScopeBinding } from "./user-data-scope.js";
|
|
42
|
+
|
|
43
|
+
type SystemEntity =
|
|
44
|
+
| ManagedUser
|
|
45
|
+
| ManagedRole
|
|
46
|
+
| ManagedDepartment
|
|
47
|
+
| ManagedMenu
|
|
48
|
+
| ManagedDictionary
|
|
49
|
+
| ManagedFeature
|
|
50
|
+
// @windy-module system.license begin
|
|
51
|
+
| ManagedLicense;
|
|
52
|
+
// @windy-module system.license end
|
|
53
|
+
|
|
54
|
+
export function createSystemEntityRepository<T extends SystemEntity>(
|
|
55
|
+
db: NodePgDatabase,
|
|
56
|
+
config: DrizzleEntityRepositoryConfig<T>,
|
|
57
|
+
transactionContext: DrizzleTransactionContext,
|
|
58
|
+
) {
|
|
59
|
+
return new DrizzleEntityRepository<T>(db, config, transactionContext);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export function userConfig(
|
|
63
|
+
seedItems: ManagedUser[],
|
|
64
|
+
): DrizzleScopedEntityRepositoryConfig<ManagedUser> {
|
|
65
|
+
return {
|
|
66
|
+
table: users,
|
|
67
|
+
idColumn: "id",
|
|
68
|
+
seedItems,
|
|
69
|
+
dataScope: {
|
|
70
|
+
drizzle: {
|
|
71
|
+
ownerId: users.id,
|
|
72
|
+
tenant: { mode: "fixed", tenantId: "single-tenant" },
|
|
73
|
+
dimensions: { departmentId: users.departmentId },
|
|
74
|
+
},
|
|
75
|
+
entity: userDataScopeBinding,
|
|
76
|
+
},
|
|
77
|
+
toRow: (item) => ({
|
|
78
|
+
...auditRow(item),
|
|
79
|
+
...pick(item, [
|
|
80
|
+
"id",
|
|
81
|
+
"username",
|
|
82
|
+
"displayName",
|
|
83
|
+
"email",
|
|
84
|
+
"phone",
|
|
85
|
+
"departmentId",
|
|
86
|
+
"roleIds",
|
|
87
|
+
"postIds",
|
|
88
|
+
"status",
|
|
89
|
+
]),
|
|
90
|
+
}),
|
|
91
|
+
toEntity: (row) =>
|
|
92
|
+
({
|
|
93
|
+
...auditEntity(row),
|
|
94
|
+
...pick(row, [
|
|
95
|
+
"id",
|
|
96
|
+
"username",
|
|
97
|
+
"displayName",
|
|
98
|
+
"email",
|
|
99
|
+
"phone",
|
|
100
|
+
"departmentId",
|
|
101
|
+
"postIds",
|
|
102
|
+
"status",
|
|
103
|
+
]),
|
|
104
|
+
roleIds: array(row.roleIds),
|
|
105
|
+
}) as ManagedUser,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function roleConfig(
|
|
110
|
+
seedItems: ManagedRole[],
|
|
111
|
+
): DrizzleEntityRepositoryConfig<ManagedRole> {
|
|
112
|
+
return {
|
|
113
|
+
table: roles,
|
|
114
|
+
idColumn: "id",
|
|
115
|
+
seedItems,
|
|
116
|
+
toRow: (item) => ({
|
|
117
|
+
...auditRow(item),
|
|
118
|
+
...pick(item, [
|
|
119
|
+
"id",
|
|
120
|
+
"code",
|
|
121
|
+
"name",
|
|
122
|
+
"dataScope",
|
|
123
|
+
"permissionKeys",
|
|
124
|
+
"menuKeys",
|
|
125
|
+
"departmentIds",
|
|
126
|
+
"status",
|
|
127
|
+
]),
|
|
128
|
+
}),
|
|
129
|
+
toEntity: (row) =>
|
|
130
|
+
({
|
|
131
|
+
...auditEntity(row),
|
|
132
|
+
...pick(row, ["id", "code", "name", "dataScope", "status"]),
|
|
133
|
+
permissionKeys: array(row.permissionKeys),
|
|
134
|
+
menuKeys: array(row.menuKeys),
|
|
135
|
+
departmentIds: array(row.departmentIds),
|
|
136
|
+
}) as ManagedRole,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export function departmentConfig(
|
|
141
|
+
seedItems: ManagedDepartment[],
|
|
142
|
+
): DrizzleEntityRepositoryConfig<ManagedDepartment> {
|
|
143
|
+
return {
|
|
144
|
+
table: departments,
|
|
145
|
+
idColumn: "id",
|
|
146
|
+
seedItems,
|
|
147
|
+
toRow: (item) => ({
|
|
148
|
+
...auditRow(item),
|
|
149
|
+
...pick(item, ["id", "parentId", "name", "code", "order", "status"]),
|
|
150
|
+
}),
|
|
151
|
+
toEntity: (row) =>
|
|
152
|
+
({
|
|
153
|
+
...auditEntity(row),
|
|
154
|
+
...pick(row, ["id", "parentId", "name", "code", "order", "status"]),
|
|
155
|
+
}) as ManagedDepartment,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function menuConfig(
|
|
160
|
+
seedItems: ManagedMenu[],
|
|
161
|
+
): DrizzleEntityRepositoryConfig<ManagedMenu> {
|
|
162
|
+
return {
|
|
163
|
+
table: menus,
|
|
164
|
+
idColumn: "id",
|
|
165
|
+
seedItems,
|
|
166
|
+
toRow: (item) => ({
|
|
167
|
+
...auditRow(item),
|
|
168
|
+
...pick(item, [
|
|
169
|
+
"id",
|
|
170
|
+
"key",
|
|
171
|
+
"title",
|
|
172
|
+
"type",
|
|
173
|
+
"order",
|
|
174
|
+
"path",
|
|
175
|
+
"component",
|
|
176
|
+
"icon",
|
|
177
|
+
"permissionKey",
|
|
178
|
+
"featureKey",
|
|
179
|
+
"parentKey",
|
|
180
|
+
"status",
|
|
181
|
+
]),
|
|
182
|
+
visible: item.visible ? "visible" : "hidden",
|
|
183
|
+
}),
|
|
184
|
+
toEntity: (row) =>
|
|
185
|
+
({
|
|
186
|
+
...auditEntity(row),
|
|
187
|
+
...pick(row, [
|
|
188
|
+
"id",
|
|
189
|
+
"key",
|
|
190
|
+
"title",
|
|
191
|
+
"type",
|
|
192
|
+
"order",
|
|
193
|
+
"path",
|
|
194
|
+
"component",
|
|
195
|
+
"icon",
|
|
196
|
+
"permissionKey",
|
|
197
|
+
"featureKey",
|
|
198
|
+
"parentKey",
|
|
199
|
+
"status",
|
|
200
|
+
]),
|
|
201
|
+
visible: row.visible !== "hidden",
|
|
202
|
+
}) as ManagedMenu,
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export function dictionaryConfig(
|
|
207
|
+
seedItems: ManagedDictionary[],
|
|
208
|
+
): DrizzleEntityRepositoryConfig<ManagedDictionary> {
|
|
209
|
+
return {
|
|
210
|
+
table: dictionaries,
|
|
211
|
+
idColumn: "id",
|
|
212
|
+
seedItems,
|
|
213
|
+
toRow: (item) => ({
|
|
214
|
+
...auditRow(item),
|
|
215
|
+
...pick(item, ["id", "code", "name", "description", "status"]),
|
|
216
|
+
items: item.items || [],
|
|
217
|
+
}),
|
|
218
|
+
toEntity: (row) =>
|
|
219
|
+
({
|
|
220
|
+
...auditEntity(row),
|
|
221
|
+
...pick(row, ["id", "code", "name", "description", "status"]),
|
|
222
|
+
items: array(row.items),
|
|
223
|
+
}) as ManagedDictionary,
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function featureConfig(
|
|
228
|
+
seedItems: ManagedFeature[],
|
|
229
|
+
): DrizzleEntityRepositoryConfig<ManagedFeature> {
|
|
230
|
+
return {
|
|
231
|
+
table: featureFlags,
|
|
232
|
+
idColumn: "key",
|
|
233
|
+
seedItems,
|
|
234
|
+
toRow: (item) => ({
|
|
235
|
+
...auditRow(item),
|
|
236
|
+
key: item.key || item.id,
|
|
237
|
+
module: item.module,
|
|
238
|
+
label: item.label,
|
|
239
|
+
description: item.description,
|
|
240
|
+
enabled: item.enabled,
|
|
241
|
+
visible: item.visible,
|
|
242
|
+
stage: item.stage,
|
|
243
|
+
licenseRequired: false,
|
|
244
|
+
licenseKey: item.requiredEntitlement,
|
|
245
|
+
allowedLicenseVersions: item.licenseVersionOverride,
|
|
246
|
+
dependencies: item.dependencies || [],
|
|
247
|
+
status: item.status,
|
|
248
|
+
}),
|
|
249
|
+
toEntity: (row) =>
|
|
250
|
+
({
|
|
251
|
+
...auditEntity(row),
|
|
252
|
+
id: String(row.key),
|
|
253
|
+
key: String(row.key),
|
|
254
|
+
module: String(row.module),
|
|
255
|
+
label: String(row.label),
|
|
256
|
+
description: row.description as string | undefined,
|
|
257
|
+
enabled: Boolean(row.enabled),
|
|
258
|
+
visible: row.visible === "hidden" ? "hidden" : "visible",
|
|
259
|
+
stage: String(row.stage || "stable") as ManagedFeature["stage"],
|
|
260
|
+
requiredEntitlement: row.licenseKey
|
|
261
|
+
? (row.licenseKey as NonNullable<
|
|
262
|
+
ManagedFeature["requiredEntitlement"]
|
|
263
|
+
>)
|
|
264
|
+
: undefined,
|
|
265
|
+
licenseVersionOverride: Array.isArray(row.allowedLicenseVersions)
|
|
266
|
+
? (row.allowedLicenseVersions as NonNullable<
|
|
267
|
+
ManagedFeature["licenseVersionOverride"]
|
|
268
|
+
>)
|
|
269
|
+
: undefined,
|
|
270
|
+
dependencies: array(row.dependencies),
|
|
271
|
+
status: String(row.status || "active") as ManagedFeature["status"],
|
|
272
|
+
}) as ManagedFeature,
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// @windy-module system.license begin
|
|
277
|
+
export function licenseConfig(
|
|
278
|
+
seedItems: ManagedLicense[],
|
|
279
|
+
): DrizzleEntityRepositoryConfig<ManagedLicense> {
|
|
280
|
+
return {
|
|
281
|
+
table: legacyLicenses,
|
|
282
|
+
idColumn: "id",
|
|
283
|
+
seedItems,
|
|
284
|
+
toRow: (item) => ({
|
|
285
|
+
...auditRow(item),
|
|
286
|
+
...pick(item, [
|
|
287
|
+
"id",
|
|
288
|
+
"licenseKey",
|
|
289
|
+
"subject",
|
|
290
|
+
"machineCode",
|
|
291
|
+
"publicKeyId",
|
|
292
|
+
"edition",
|
|
293
|
+
"modules",
|
|
294
|
+
"status",
|
|
295
|
+
]),
|
|
296
|
+
issuedAt: date(item.issuedAt),
|
|
297
|
+
expiresAt: item.expiresAt ? date(item.expiresAt) : undefined,
|
|
298
|
+
payload: { modules: item.modules },
|
|
299
|
+
signature: "",
|
|
300
|
+
}),
|
|
301
|
+
toEntity: (row) =>
|
|
302
|
+
({
|
|
303
|
+
...auditEntity(row),
|
|
304
|
+
...pick(row, [
|
|
305
|
+
"id",
|
|
306
|
+
"licenseKey",
|
|
307
|
+
"subject",
|
|
308
|
+
"machineCode",
|
|
309
|
+
"publicKeyId",
|
|
310
|
+
"edition",
|
|
311
|
+
"status",
|
|
312
|
+
]),
|
|
313
|
+
modules: array(row.modules),
|
|
314
|
+
issuedAt: iso(row.issuedAt),
|
|
315
|
+
expiresAt: optionalIso(row.expiresAt),
|
|
316
|
+
}) as ManagedLicense,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
// @windy-module system.license end
|