galaxy-opc-plugin 0.2.8 → 0.3.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "galaxy-opc-plugin",
3
- "version": "0.2.8",
3
+ "version": "0.3.0",
4
4
  "description": "星环 Galaxy OPC — 一人公司孵化与赋能平台 OpenClaw 插件",
5
5
  "keywords": [
6
6
  "openclaw",
@@ -208,21 +208,17 @@ export function registerCompanyRoutes(api: OpenClawPluginApi, db: OpcDatabase, g
208
208
 
209
209
  const apiAny = api as unknown as {
210
210
  registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
211
- registerHttpRoute?: (r: { path: string | RegExp; handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void> }) => void;
211
+ registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
212
212
  };
213
213
 
214
214
  if (typeof apiAny.registerHttpHandler === "function") {
215
215
  apiAny.registerHttpHandler(handler);
216
216
  } else if (typeof apiAny.registerHttpRoute === "function") {
217
217
  apiAny.registerHttpRoute({
218
- path: /^\/opc\/api\/companies(?:\/.*)?$/,
219
- handler: async (req, res) => {
220
- const handled = await handler(req, res);
221
- if (!handled) {
222
- res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
223
- res.end(JSON.stringify({ error: "Not found" }));
224
- }
225
- },
218
+ path: "/opc/api/companies",
219
+ handler,
220
+ auth: "gateway",
221
+ match: "prefix",
226
222
  });
227
223
  } else {
228
224
  throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
@@ -6,6 +6,7 @@
6
6
  * POST /opc/admin/api/alerts/:id/dismiss — 忽略预警
7
7
  */
8
8
 
9
+ import type { IncomingMessage, ServerResponse } from "node:http";
9
10
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
10
11
  import type { OpcDatabase } from "../db/index.js";
11
12
  import {
@@ -60,10 +61,14 @@ interface TodoRow {
60
61
  * 注册 Dashboard API 路由
61
62
  */
62
63
  export function registerDashboardApiRoutes(api: OpenClawPluginApi, db: OpcDatabase): void {
63
- // GET /opc/admin/api/dashboard
64
- api.registerHttpRoute({
65
- path: "/opc/admin/api/dashboard",
66
- handler: (req, res) => {
64
+ const handler = async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
65
+ const rawUrl = req.url ?? "";
66
+ const urlObj = new URL(rawUrl, "http://localhost");
67
+ const pathname = urlObj.pathname;
68
+ const method = req.method?.toUpperCase() ?? "GET";
69
+
70
+ // GET /opc/admin/api/dashboard
71
+ if (pathname === "/opc/admin/api/dashboard" && method === "GET") {
67
72
  try {
68
73
  const data = getDashboardData(db);
69
74
  const html = generateDashboardHtml(data);
@@ -73,22 +78,19 @@ export function registerDashboardApiRoutes(api: OpenClawPluginApi, db: OpcDataba
73
78
  res.writeHead(500, { "Content-Type": "application/json; charset=utf-8" });
74
79
  res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
75
80
  }
76
- },
77
- });
81
+ return true;
82
+ }
78
83
 
79
- // POST /opc/admin/api/alerts/:id/dismiss
80
- api.registerHttpRoute({
81
- path: "/opc/admin/api/alerts/:id/dismiss",
82
- handler: async (req, res) => {
84
+ // POST /opc/admin/api/alerts/:id/dismiss
85
+ const alertMatch = pathname.match(/^\/opc\/admin\/api\/alerts\/([^/]+)\/dismiss$/);
86
+ if (alertMatch && method === "POST") {
83
87
  try {
84
- const url = new URL(req.url || "", `http://${req.headers.host}`);
85
- const pathParts = url.pathname.split("/");
86
- const alertId = pathParts[pathParts.length - 2]; // .../alerts/{id}/dismiss
88
+ const alertId = alertMatch[1];
87
89
 
88
90
  if (!alertId) {
89
91
  res.writeHead(400, { "Content-Type": "application/json; charset=utf-8" });
90
92
  res.end(JSON.stringify({ error: "Missing alert ID" }));
91
- return;
93
+ return true;
92
94
  }
93
95
 
94
96
  const now = new Date().toISOString();
@@ -109,8 +111,27 @@ export function registerDashboardApiRoutes(api: OpenClawPluginApi, db: OpcDataba
109
111
  res.writeHead(500, { "Content-Type": "application/json; charset=utf-8" });
110
112
  res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
111
113
  }
112
- },
113
- });
114
+ return true;
115
+ }
116
+
117
+ return false;
118
+ };
119
+
120
+ const apiAny = api as unknown as {
121
+ registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
122
+ registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
123
+ };
124
+
125
+ if (typeof apiAny.registerHttpHandler === "function") {
126
+ apiAny.registerHttpHandler(handler);
127
+ } else if (typeof apiAny.registerHttpRoute === "function") {
128
+ apiAny.registerHttpRoute({
129
+ path: "/opc/admin/api",
130
+ handler,
131
+ auth: "gateway",
132
+ match: "prefix",
133
+ });
134
+ }
114
135
  }
115
136
 
116
137
  /**
package/src/api/routes.ts CHANGED
@@ -5,7 +5,6 @@
5
5
  import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
6
6
  import type { OpcDatabase } from "../db/index.js";
7
7
  import { registerCompanyRoutes } from "./companies.js";
8
- import { registerDashboardApiRoutes } from "./dashboard.js";
9
8
 
10
9
  /**
11
10
  * 从 OpenClaw 配置中读取 gateway auth token。
@@ -26,6 +25,5 @@ export function registerHttpRoutes(api: OpenClawPluginApi, db: OpcDatabase): voi
26
25
  const gatewayToken = getGatewayToken(api);
27
26
 
28
27
  registerCompanyRoutes(api, db, gatewayToken);
29
- registerDashboardApiRoutes(api, db);
30
28
  api.logger.info("opc: 已注册 HTTP API 路由");
31
29
  }
@@ -72,7 +72,7 @@ export function registerConfigUiRoutes(api: OpenClawPluginApi, db: OpcDatabase,
72
72
 
73
73
  // GET /opc/admin/api/payments/:id
74
74
  api.registerHttpRoute({
75
- path: /^\/opc\/admin\/api\/payments\/([^/]+)$/,
75
+ path: '/opc/admin/api/payments',
76
76
  handler: async (req, res) => {
77
77
  const match = req.url?.match(/^\/opc\/admin\/api\/payments\/([^/]+)$/);
78
78
  if (!match) {
@@ -135,7 +135,7 @@ export function registerConfigUiRoutes(api: OpenClawPluginApi, db: OpcDatabase,
135
135
 
136
136
  // PUT /opc/admin/api/payments/:id - 更新收付款
137
137
  api.registerHttpRoute({
138
- path: /^\/opc\/admin\/api\/payments\/([^/]+)$/,
138
+ path: '/opc/admin/api/payments',
139
139
  handler: async (req, res) => {
140
140
  if (req.method !== 'PUT') return false;
141
141
 
@@ -180,7 +180,7 @@ export function registerConfigUiRoutes(api: OpenClawPluginApi, db: OpcDatabase,
180
180
 
181
181
  // POST /opc/admin/api/payments/:id/record - 记账
182
182
  api.registerHttpRoute({
183
- path: /^\/opc\/admin\/api\/payments\/([^/]+)\/record$/,
183
+ path: '/opc/admin/api/payments',
184
184
  handler: async (req, res) => {
185
185
  if (req.method !== 'POST') return false;
186
186
 
@@ -3123,32 +3123,32 @@ function getCanvasJs(): string {
3123
3123
 
3124
3124
  /* ── Route registration ───────────────────────────────────── */
3125
3125
 
3126
- export function registerConfigUi(api: OpenClawPluginApi, db: OpcDatabase, gatewayToken?: string): void {
3126
+ export function registerConfigUi(api: OpenClawPluginApi, db: OpcDatabase, gatewayToken?: string): void {
3127
3127
  // 注册 Dashboard API 路由
3128
3128
  registerDashboardApiRoutes(api, db);
3129
3129
 
3130
- const handler = async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
3130
+ const handler = async (req: IncomingMessage, res: ServerResponse): Promise<boolean> => {
3131
3131
  const rawUrl = req.url ?? "";
3132
3132
  const urlObj = new URL(rawUrl, "http://localhost");
3133
3133
  const pathname = urlObj.pathname;
3134
3134
  const method = req.method?.toUpperCase() ?? "GET";
3135
3135
 
3136
- if (!pathname.startsWith("/opc/admin")) {
3137
- return false;
3138
- }
3139
-
3140
- // Normalize accidental SPA deep-links (e.g. /opc/admin/chat) back to OPC admin root.
3141
- // Without this, users may land on OpenClaw's default chat UI and think OPC admin failed to load.
3142
- if (
3143
- !pathname.startsWith("/opc/admin/api/")
3144
- && pathname !== "/opc/admin"
3145
- && pathname !== "/opc/admin/"
3146
- ) {
3147
- const tokenParam = gatewayToken ? `?token=${encodeURIComponent(gatewayToken)}` : "";
3148
- res.writeHead(302, { Location: `/opc/admin${tokenParam}` });
3149
- res.end();
3150
- return true;
3151
- }
3136
+ if (!pathname.startsWith("/opc/admin")) {
3137
+ return false;
3138
+ }
3139
+
3140
+ // Normalize accidental SPA deep-links (e.g. /opc/admin/chat) back to OPC admin root.
3141
+ // Without this, users may land on OpenClaw's default chat UI and think OPC admin failed to load.
3142
+ if (
3143
+ !pathname.startsWith("/opc/admin/api/")
3144
+ && pathname !== "/opc/admin"
3145
+ && pathname !== "/opc/admin/"
3146
+ ) {
3147
+ const tokenParam = gatewayToken ? `?token=${encodeURIComponent(gatewayToken)}` : "";
3148
+ res.writeHead(302, { Location: `/opc/admin${tokenParam}` });
3149
+ res.end();
3150
+ return true;
3151
+ }
3152
3152
 
3153
3153
  // API 端点需要认证
3154
3154
  if (pathname.startsWith("/opc/admin/api/") && gatewayToken) {
@@ -4169,29 +4169,25 @@ export function registerConfigUi(api: OpenClawPluginApi, db: OpcDatabase, gatewa
4169
4169
  res.end(JSON.stringify({ error: err instanceof Error ? err.message : String(err) }));
4170
4170
  return true;
4171
4171
  }
4172
- };
4173
-
4174
- const apiAny = api as unknown as {
4175
- registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
4176
- registerHttpRoute?: (r: { path: string | RegExp; handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void> }) => void;
4177
- };
4178
-
4179
- if (typeof apiAny.registerHttpHandler === "function") {
4180
- apiAny.registerHttpHandler(handler);
4181
- } else if (typeof apiAny.registerHttpRoute === "function") {
4182
- apiAny.registerHttpRoute({
4183
- path: /^\/opc\/admin(?:\/.*)?$/,
4184
- handler: async (req, res) => {
4185
- const handled = await handler(req, res);
4186
- if (!handled) {
4187
- res.writeHead(404, { "Content-Type": "application/json; charset=utf-8" });
4188
- res.end(JSON.stringify({ error: "Not found" }));
4189
- }
4190
- },
4191
- });
4192
- } else {
4193
- throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
4194
- }
4172
+ };
4173
+
4174
+ const apiAny = api as unknown as {
4175
+ registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
4176
+ registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
4177
+ };
4178
+
4179
+ if (typeof apiAny.registerHttpHandler === "function") {
4180
+ apiAny.registerHttpHandler(handler);
4181
+ } else if (typeof apiAny.registerHttpRoute === "function") {
4182
+ apiAny.registerHttpRoute({
4183
+ path: "/opc/admin",
4184
+ handler,
4185
+ auth: "gateway",
4186
+ match: "prefix",
4187
+ });
4188
+ } else {
4189
+ throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");
4190
+ }
4195
4191
 
4196
4192
  api.logger.info("opc: 已注册配置管理 UI (/opc/admin)");
4197
4193
  }
@@ -317,21 +317,17 @@ export function registerLandingPage(api: OpenClawPluginApi): void {
317
317
 
318
318
  const apiAny = api as unknown as {
319
319
  registerHttpHandler?: (h: (req: IncomingMessage, res: ServerResponse) => Promise<boolean> | boolean) => void;
320
- registerHttpRoute?: (r: { path: string | RegExp; handler: (req: IncomingMessage, res: ServerResponse) => void | Promise<void> }) => void;
320
+ registerHttpRoute?: (r: { path: string; handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void; auth: string; match?: string }) => void;
321
321
  };
322
322
 
323
323
  if (typeof apiAny.registerHttpHandler === "function") {
324
324
  apiAny.registerHttpHandler(handler);
325
325
  } else if (typeof apiAny.registerHttpRoute === "function") {
326
326
  apiAny.registerHttpRoute({
327
- path: /^\/$/,
328
- handler: async (req, res) => {
329
- const handled = await handler(req, res);
330
- if (!handled) {
331
- res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" });
332
- res.end("Not found");
333
- }
334
- },
327
+ path: "/",
328
+ handler,
329
+ auth: "plugin",
330
+ match: "prefix",
335
331
  });
336
332
  } else {
337
333
  throw new Error("No compatible HTTP registration API found on OpenClaw plugin API");