@yinuo-ngm/server 1.0.3 → 1.0.4

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.
@@ -14,4 +14,5 @@ exports.default = (0, fastify_plugin_1.default)(async function routesPlugin(fast
14
14
  await fastify.register(routes_1.configRoutes, { prefix: '/api/config' });
15
15
  await fastify.register(routes_1.dashboardRoutes, { prefix: '/api/dashboard' });
16
16
  await fastify.register(routes_1.rssRoutes, { prefix: '/api/rss' });
17
+ await fastify.register(routes_1.spriteRoutes, { prefix: '/api/sprite' });
17
18
  });
@@ -6,17 +6,44 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  const fastify_plugin_1 = __importDefault(require("fastify-plugin"));
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const static_1 = __importDefault(require("@fastify/static"));
9
+ const env_1 = require("../env");
10
+ const fs_1 = __importDefault(require("fs"));
9
11
  exports.default = (0, fastify_plugin_1.default)(async function staticPlugin(fastify) {
10
12
  const webRoot = path_1.default.resolve(__dirname, "../../www/browser");
13
+ const dataDir = env_1.env.dataDir;
14
+ const spritesRoot = path_1.default.join(dataDir, "sprites");
15
+ const spriteCssRoot = path_1.default.join(dataDir, "sprite-css");
16
+ for (const dir of [dataDir, spritesRoot, spriteCssRoot]) {
17
+ if (!fs_1.default.existsSync(dir))
18
+ fs_1.default.mkdirSync(dir, { recursive: true });
19
+ }
11
20
  fastify.log.info(`[static] serving webapp from ${webRoot}`);
21
+ fastify.log.info(`[static] dataDir=${dataDir}`);
22
+ fastify.log.info(`[static] serving sprites from ${spritesRoot} at /sprites/`);
23
+ fastify.log.info(`[static] serving sprite-css from ${spriteCssRoot} at /sprite-css/`);
12
24
  await fastify.register(static_1.default, {
13
25
  root: webRoot,
14
26
  index: "index.html",
27
+ decorateReply: true,
28
+ });
29
+ await fastify.register(static_1.default, {
30
+ root: spritesRoot,
31
+ prefix: "/sprites/",
32
+ decorateReply: false,
33
+ });
34
+ await fastify.register(static_1.default, {
35
+ root: spriteCssRoot,
36
+ prefix: "/sprite-css/",
37
+ decorateReply: false,
15
38
  });
16
39
  fastify.setNotFoundHandler((req, reply) => {
17
- if (req.method === "GET" &&
18
- !req.url.startsWith("/api") &&
19
- !req.url.startsWith("/ws")) {
40
+ const url = req.url || "";
41
+ const isSpaFallbackCandidate = req.method === "GET" &&
42
+ !url.startsWith("/api") &&
43
+ !url.startsWith("/ws") &&
44
+ !url.startsWith("/sprites/") &&
45
+ !url.startsWith("/sprite-css/");
46
+ if (isSpaFallbackCandidate) {
20
47
  return reply.sendFile("index.html");
21
48
  }
22
49
  reply.code(404).send({ ok: false, message: "Not Found" });
@@ -4,6 +4,7 @@ import depsRoutes from './deps.route';
4
4
  import fsRoutes from './fs.routes';
5
5
  import projectRoutes from './project.routes';
6
6
  import rssRoutes from './rss.routes';
7
+ import { spriteRoutes } from './sprite.routes';
7
8
  import systemRoutes from './system.routes';
8
9
  import taskRoutes from './task.routes';
9
- export { configRoutes, depsRoutes, fsRoutes, projectRoutes, systemRoutes, taskRoutes, dashboardRoutes, rssRoutes, };
10
+ export { configRoutes, depsRoutes, fsRoutes, projectRoutes, systemRoutes, taskRoutes, dashboardRoutes, rssRoutes, spriteRoutes };
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.rssRoutes = exports.dashboardRoutes = exports.taskRoutes = exports.systemRoutes = exports.projectRoutes = exports.fsRoutes = exports.depsRoutes = exports.configRoutes = void 0;
6
+ exports.spriteRoutes = exports.rssRoutes = exports.dashboardRoutes = exports.taskRoutes = exports.systemRoutes = exports.projectRoutes = exports.fsRoutes = exports.depsRoutes = exports.configRoutes = void 0;
7
7
  const config_routes_1 = __importDefault(require("./config.routes"));
8
8
  exports.configRoutes = config_routes_1.default;
9
9
  const dashboard_routes_1 = __importDefault(require("./dashboard.routes"));
@@ -16,6 +16,8 @@ const project_routes_1 = __importDefault(require("./project.routes"));
16
16
  exports.projectRoutes = project_routes_1.default;
17
17
  const rss_routes_1 = __importDefault(require("./rss.routes"));
18
18
  exports.rssRoutes = rss_routes_1.default;
19
+ const sprite_routes_1 = require("./sprite.routes");
20
+ Object.defineProperty(exports, "spriteRoutes", { enumerable: true, get: function () { return sprite_routes_1.spriteRoutes; } });
19
21
  const system_routes_1 = __importDefault(require("./system.routes"));
20
22
  exports.systemRoutes = system_routes_1.default;
21
23
  const task_routes_1 = __importDefault(require("./task.routes"));
@@ -0,0 +1,2 @@
1
+ import { FastifyInstance } from "fastify";
2
+ export declare function spriteRoutes(fastify: FastifyInstance): Promise<void>;
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.spriteRoutes = spriteRoutes;
7
+ const node_fs_1 = __importDefault(require("node:fs"));
8
+ const node_path_1 = __importDefault(require("node:path"));
9
+ const env_1 = require("../env");
10
+ const sprite_1 = require("@yinuo-ngm/sprite");
11
+ function ensureDir(dir) {
12
+ if (!node_fs_1.default.existsSync(dir))
13
+ node_fs_1.default.mkdirSync(dir, { recursive: true });
14
+ }
15
+ async function spriteRoutes(fastify) {
16
+ fastify.post("/generate", async (req) => {
17
+ try {
18
+ const { projectId } = req.params;
19
+ const body = req.body || {};
20
+ const group = String(body.group || "").trim();
21
+ if (!group) {
22
+ throw new Error("group is required");
23
+ }
24
+ const prefix = (body.prefix || "sl").trim() || "sl";
25
+ const forceRefresh = !!body.forceRefresh;
26
+ const algorithm = body.algorithm || "binary-tree";
27
+ const persistLess = body.persistLess ?? true;
28
+ const iconsRoot = node_path_1.default.join(env_1.env.dataDir, "icons", projectId, "icons");
29
+ const groupDir = node_path_1.default.join(iconsRoot, group);
30
+ if (!node_fs_1.default.existsSync(groupDir)) {
31
+ throw new Error(`Icon group not found: ${groupDir}`);
32
+ }
33
+ const outDir = node_path_1.default.join(env_1.env.dataDir, "sprites", projectId);
34
+ ensureDir(outDir);
35
+ const spriteUrl = `/sprites/${encodeURIComponent(projectId)}/${encodeURIComponent(group)}.png`;
36
+ const type = (0, sprite_1.detectGroupType)(groupDir);
37
+ let data;
38
+ if (type === "mixed") {
39
+ throw new Error(`分组 ${group} 同时存在 png 与 svg,请统一格式(建议拆分目录)`);
40
+ }
41
+ if (type === "svg") {
42
+ data = await (0, sprite_1.generateSvgGroup)({
43
+ group,
44
+ groupDir,
45
+ prefix,
46
+ urlResolver: ({ group, file }) => `/icons/${encodeURIComponent(projectId)}/icons/${encodeURIComponent(group)}/${encodeURIComponent(file)}`,
47
+ });
48
+ }
49
+ else {
50
+ data = await (0, sprite_1.generatePngGroup)({
51
+ group,
52
+ groupDir,
53
+ outDir,
54
+ spriteUrl,
55
+ css: {
56
+ prefix,
57
+ spriteUrlResolver: ({ spriteUrl }) => spriteUrl,
58
+ },
59
+ cache: {
60
+ enabled: true,
61
+ forceRefresh,
62
+ persistLess,
63
+ },
64
+ spritesmith: { algorithm },
65
+ });
66
+ }
67
+ return data;
68
+ }
69
+ catch (e) {
70
+ req.log.error(e);
71
+ throw new Error("Failed to generate sprite");
72
+ }
73
+ });
74
+ }
package/package.json CHANGED
@@ -1,33 +1,37 @@
1
- {
2
- "name": "@yinuo-ngm/server",
3
- "version": "1.0.3",
4
- "description": "",
5
- "main": "lib/index.js",
6
- "keywords": [],
7
- "author": "ZhangJing",
8
- "license": "ISC",
9
- "types": "lib/index.d.ts",
10
- "files": [
11
- "lib",
12
- "www"
13
- ],
14
- "scripts": {
15
- "dev": "tsx watch src/index.ts",
16
- "build": "tsc -p tsconfig.build.json",
17
- "start": "node lib/index.js"
18
- },
19
- "dependencies": {
20
- "@fastify/static": "^9.0.0",
21
- "@fastify/websocket": "^11.2.0",
22
- "@yinuo-ngm/core": "^0.1.2",
23
- "fastify": "^5.6.2",
24
- "fastify-plugin": "^5.1.0",
25
- "launch-editor": "^2.12.0",
26
- "pino-pretty": "^13.1.3",
27
- "rss-parser": "^3.13.0"
28
- },
29
- "devDependencies": {
30
- "@types/node": "^25.2.0",
31
- "tsx": "^4.21.0"
32
- }
33
- }
1
+ {
2
+ "name": "@yinuo-ngm/server",
3
+ "version": "1.0.4",
4
+ "description": "",
5
+ "main": "lib/index.js",
6
+ "keywords": [],
7
+ "author": "ZhangJing",
8
+ "license": "ISC",
9
+ "types": "lib/index.d.ts",
10
+ "files": [
11
+ "lib",
12
+ "www"
13
+ ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
17
+ "scripts": {
18
+ "dev": "tsx watch src/index.ts",
19
+ "build": "tsc -p tsconfig.json",
20
+ "start": "node lib/index.js"
21
+ },
22
+ "dependencies": {
23
+ "@fastify/static": "^9.0.0",
24
+ "@fastify/websocket": "^11.2.0",
25
+ "@yinuo-ngm/core": "^0.1.3",
26
+ "@yinuo-ngm/sprite": "^0.1.1",
27
+ "fastify": "^5.6.2",
28
+ "fastify-plugin": "^5.1.0",
29
+ "launch-editor": "^2.12.0",
30
+ "pino-pretty": "^13.1.3",
31
+ "rss-parser": "^3.13.0"
32
+ },
33
+ "devDependencies": {
34
+ "tsx": "^4.21.0"
35
+ },
36
+ "gitHead": "ebfaab3c1457d597f904b5d121292f5a84486609"
37
+ }