@yinuo-ngm/server 1.0.20 → 1.0.22
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/lib/app.js +0 -4
- package/lib/env.js +5 -1
- package/lib/plugins/success-handle.plugin.js +1 -1
- package/lib/plugins/ws/topics/nginx.ws.js +1 -1
- package/lib/plugins/ws/ws.context.js +3 -1
- package/lib/plugins/ws/ws.plugin.js +14 -2
- package/lib/routes/api-client/collection.routes.js +35 -35
- package/lib/routes/api-client/env.routes.js +12 -8
- package/lib/routes/api-client/history.routes.js +10 -5
- package/lib/routes/api-client/request.routes.js +14 -8
- package/lib/routes/api-client/route-mappers.d.ts +7 -0
- package/lib/routes/api-client/route-mappers.js +78 -0
- package/lib/routes/api-client/send.routes.js +12 -8
- package/lib/routes/config.routes.js +73 -49
- package/lib/routes/deps.route.js +47 -5
- package/lib/routes/index.js +5 -3
- package/lib/routes/nginx/nginx-config.routes.js +3 -3
- package/lib/routes/nginx/nginx-lifecycle.routes.js +14 -13
- package/lib/routes/nginx/nginx-module.routes.js +6 -6
- package/lib/routes/nginx/nginx-route.context.d.ts +16 -1
- package/lib/routes/nginx/nginx-route.context.js +136 -1
- package/lib/routes/nginx/nginx-server.routes.js +5 -5
- package/lib/routes/node-runtime.routes.d.ts +2 -0
- package/lib/routes/node-runtime.routes.js +69 -0
- package/lib/routes/project.routes.js +117 -13
- package/lib/routes/sprite/sprite-browse.routes.d.ts +2 -0
- package/lib/routes/sprite/sprite-browse.routes.js +137 -0
- package/lib/routes/sprite/sprite-quick.utils.d.ts +19 -0
- package/lib/routes/sprite/sprite-quick.utils.js +247 -0
- package/lib/routes/sprite/sprite.routes.d.ts +2 -0
- package/lib/routes/sprite/sprite.routes.js +212 -0
- package/lib/routes/sprite-browse.routes.js +17 -11
- package/lib/routes/sprite.routes.d.ts +1 -1
- package/lib/routes/sprite.routes.js +68 -11
- package/lib/routes/svn.routes.js +48 -14
- package/lib/routes/task.routes.js +99 -7
- package/package.json +7 -7
- package/www/3rdpartylicenses.txt +5 -5
- package/www/browser/{chunk-OZCK4XVV.js → chunk-2VJVGBXG.js} +1 -1
- package/www/browser/{chunk-FL6GDGHW.js → chunk-3ODVU46S.js} +1 -1
- package/www/browser/chunk-442QFABJ.js +1 -0
- package/www/browser/{chunk-WD2EKZQC.js → chunk-6J6G7JEP.js} +1 -1
- package/www/browser/{chunk-7U44RF5F.js → chunk-6UFDNETG.js} +1 -1
- package/www/browser/{chunk-75W3GVSO.js → chunk-7AKVG375.js} +1 -1
- package/www/browser/chunk-7GLWEFTM.js +1 -0
- package/www/browser/{chunk-DIJPUYIA.js → chunk-7QR6RHLA.js} +1 -1
- package/www/browser/{chunk-HJTXXSMC.js → chunk-CO3CQHKV.js} +1 -1
- package/www/browser/{chunk-3XNNQFWR.js → chunk-CPJTSA6E.js} +1 -1
- package/www/browser/chunk-DENFXXOY.js +1 -0
- package/www/browser/{chunk-HDNG236Q.js → chunk-HC5KLPHD.js} +1 -1
- package/www/browser/chunk-HJAP6WBI.js +1 -0
- package/www/browser/{chunk-N2PELLMM.js → chunk-JM6DCZP6.js} +7 -7
- package/www/browser/chunk-K6C5ZIV2.js +20 -0
- package/www/browser/chunk-M6NZ6C2R.js +2 -0
- package/www/browser/{chunk-RGOYDY7H.js → chunk-MBPB43C6.js} +1 -1
- package/www/browser/chunk-MPLGMTLT.js +3 -0
- package/www/browser/chunk-NNOWADVM.js +1 -0
- package/www/browser/{chunk-M4QRBV3K.js → chunk-NREWZQVN.js} +1 -1
- package/www/browser/{chunk-6YYNHZ2A.js → chunk-OUGN4APK.js} +1 -1
- package/www/browser/chunk-PB2LGZNW.js +1 -0
- package/www/browser/chunk-PDI3HSSH.js +4 -0
- package/www/browser/chunk-PUG3VNTI.js +3 -0
- package/www/browser/{chunk-QJP5F735.js → chunk-PY3AUTHC.js} +1 -1
- package/www/browser/{chunk-3M56F2S2.js → chunk-R4HSZU2J.js} +1 -1
- package/www/browser/{chunk-DE6E23ET.js → chunk-RKK4I2RT.js} +1 -1
- package/www/browser/chunk-RMIYLAEM.js +1 -0
- package/www/browser/chunk-RZA3IFQV.js +2 -0
- package/www/browser/{chunk-K7PESFPY.js → chunk-SD2HFD54.js} +1 -1
- package/www/browser/{chunk-BTQIUVTQ.js → chunk-SEJGGBE2.js} +1 -1
- package/www/browser/chunk-SSCUT2GF.js +1 -0
- package/www/browser/chunk-TCBOC5FF.js +1 -0
- package/www/browser/{chunk-AZ6SIMYH.js → chunk-TS5ZQYYY.js} +1 -1
- package/www/browser/chunk-TVJHI463.js +1 -0
- package/www/browser/{chunk-YNW4HEJO.js → chunk-TXAXE73U.js} +17 -17
- package/www/browser/{chunk-4X42HB6N.js → chunk-U2YWR3HF.js} +1 -1
- package/www/browser/{chunk-D2ODDESN.js → chunk-U3EUR236.js} +1 -1
- package/www/browser/chunk-UKCMUTYL.js +1 -0
- package/www/browser/{chunk-DLGJD6YU.js → chunk-UPOORT3S.js} +1 -1
- package/www/browser/chunk-VW3S7C2Z.js +1 -0
- package/www/browser/chunk-VZYJ3MSW.js +15 -0
- package/www/browser/{chunk-AELTP6YN.js → chunk-WCHN62X6.js} +1 -1
- package/www/browser/chunk-WWIPELAV.js +1 -0
- package/www/browser/{chunk-B3C35ET3.js → chunk-WYNERG74.js} +1 -1
- package/www/browser/{chunk-ZTDLWBW5.js → chunk-XJDJL3TQ.js} +1 -1
- package/www/browser/{chunk-EEDA5U4V.js → chunk-YV6QPLF5.js} +1 -1
- package/www/browser/{chunk-ONXBYGIG.js → chunk-YVRGRFK2.js} +1 -1
- package/www/browser/index.html +1 -1
- package/www/browser/main-7GYUOEJY.js +38 -0
- package/lib/plugins/api-client.plugin.d.ts +0 -3
- package/lib/plugins/api-client.plugin.js +0 -55
- package/lib/plugins/nginx.binding.store.d.ts +0 -4
- package/lib/plugins/nginx.binding.store.js +0 -39
- package/lib/plugins/nginx.plugin.d.ts +0 -3
- package/lib/plugins/nginx.plugin.js +0 -23
- package/www/browser/chunk-2L7NUOMX.js +0 -2
- package/www/browser/chunk-2NZJ7CN2.js +0 -20
- package/www/browser/chunk-3CM4SKDO.js +0 -15
- package/www/browser/chunk-3OHBKMAA.js +0 -1
- package/www/browser/chunk-4LBSLURA.js +0 -1
- package/www/browser/chunk-5DYX4DUX.js +0 -11
- package/www/browser/chunk-6SYVDN5L.js +0 -1
- package/www/browser/chunk-AMXRL4GR.js +0 -1
- package/www/browser/chunk-AV2ZODEH.js +0 -1
- package/www/browser/chunk-CN5J4WNO.js +0 -1
- package/www/browser/chunk-FK6Z4HLL.js +0 -1
- package/www/browser/chunk-FXCG34QS.js +0 -1
- package/www/browser/chunk-H5HGMOE6.js +0 -1
- package/www/browser/chunk-HB3HECPD.js +0 -1
- package/www/browser/chunk-HUMCWAKJ.js +0 -3
- package/www/browser/chunk-IKB3EQCP.js +0 -2
- package/www/browser/chunk-OSBDR36P.js +0 -1
- package/www/browser/chunk-XLFHB7RS.js +0 -3
- package/www/browser/main-N64WJCHX.js +0 -34
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MISC_PROXY_PREFIX = exports.QUICK_SPRITE_PROXY_PREFIX = void 0;
|
|
4
|
+
exports.getBaseUrl = getBaseUrl;
|
|
5
|
+
exports.buildQuickPreviewUrl = buildQuickPreviewUrl;
|
|
6
|
+
exports.quickFetch = quickFetch;
|
|
7
|
+
exports.resolveEnabledRemoteProjectId = resolveEnabledRemoteProjectId;
|
|
8
|
+
exports.fetchRemoteProject = fetchRemoteProject;
|
|
9
|
+
exports.mapToGroup = mapToGroup;
|
|
10
|
+
exports.mapQuickGroupsToSnapshot = mapQuickGroupsToSnapshot;
|
|
11
|
+
exports.copyRawResponseHeaders = copyRawResponseHeaders;
|
|
12
|
+
exports.hasQuickSprite = hasQuickSprite;
|
|
13
|
+
exports.fetchAndCacheRemoteMiscImages = fetchAndCacheRemoteMiscImages;
|
|
14
|
+
exports.buildBrowseFromCache = buildBrowseFromCache;
|
|
15
|
+
exports.buildRemoteMiscUrl = buildRemoteMiscUrl;
|
|
16
|
+
const errors_1 = require("@yinuo-ngm/errors");
|
|
17
|
+
const sprite_1 = require("@yinuo-ngm/sprite");
|
|
18
|
+
function getBaseUrl(cfg) {
|
|
19
|
+
return (cfg?.quickSpriteBaseUrl?.trim() ||
|
|
20
|
+
"http://192.168.1.31:7010").replace(/\/+$/, "");
|
|
21
|
+
}
|
|
22
|
+
exports.QUICK_SPRITE_PROXY_PREFIX = "/api/sprite/proxy";
|
|
23
|
+
function buildQuickPreviewUrl(localProjectId, group) {
|
|
24
|
+
return `${exports.QUICK_SPRITE_PROXY_PREFIX}/${encodeURIComponent(localProjectId)}/${encodeURIComponent(group)}.png`;
|
|
25
|
+
}
|
|
26
|
+
async function quickFetch(fastify, baseUrl, path, init) {
|
|
27
|
+
const url = `${baseUrl}${path}`;
|
|
28
|
+
fastify.log.info(`[sprite-quick] → ${init?.method || "GET"} ${url}`);
|
|
29
|
+
let res;
|
|
30
|
+
try {
|
|
31
|
+
res = await fetch(url, {
|
|
32
|
+
...init,
|
|
33
|
+
headers: {
|
|
34
|
+
"Content-Type": "application/json",
|
|
35
|
+
...init?.headers,
|
|
36
|
+
},
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
fastify.log.error(`[sprite-quick] ✗ 无法连接远端 ${url}: ${err?.message || err}`);
|
|
41
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.INTERNAL_ERROR, `无法连接远端雪碧图服务 (${baseUrl}):${err?.message || err}`);
|
|
42
|
+
}
|
|
43
|
+
if (!res.ok) {
|
|
44
|
+
const text = await res.text().catch(() => "");
|
|
45
|
+
fastify.log.error(`[sprite-quick] ← ${res.status} ${url}: ${text}`);
|
|
46
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.INTERNAL_ERROR, `远端服务返回 ${res.status}: ${text || res.statusText}`);
|
|
47
|
+
}
|
|
48
|
+
const data = (await res.json());
|
|
49
|
+
fastify.log.info(`[sprite-quick] ← ${res.status} ${url}`);
|
|
50
|
+
return data;
|
|
51
|
+
}
|
|
52
|
+
async function resolveEnabledRemoteProjectId(fastify, projectId) {
|
|
53
|
+
const cfg = await fastify.core.sprite.getConfig(projectId);
|
|
54
|
+
if (!cfg?.quickSpriteEnabled || !cfg?.quickSpriteProjectId)
|
|
55
|
+
return null;
|
|
56
|
+
return cfg.quickSpriteProjectId;
|
|
57
|
+
}
|
|
58
|
+
async function fetchRemoteProject(fastify, baseUrl, quickProjectId) {
|
|
59
|
+
try {
|
|
60
|
+
return await quickFetch(fastify, baseUrl, `/api/projects/${encodeURIComponent(quickProjectId)}`);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function mapToGroup(result, localProjectId, prefix, spriteUrlTemplate) {
|
|
67
|
+
const classes = (result.classes || []).map((c) => ({
|
|
68
|
+
name: c.name,
|
|
69
|
+
className: `${prefix}-${result.group.split("-")[0]}-${c.name}`,
|
|
70
|
+
x: c.x,
|
|
71
|
+
y: c.y,
|
|
72
|
+
width: c.width,
|
|
73
|
+
height: c.height,
|
|
74
|
+
}));
|
|
75
|
+
const derived = deriveSpriteSize(classes);
|
|
76
|
+
const spriteWidth = derived.width > 0 ? derived.width : result.width || 0;
|
|
77
|
+
const spriteHeight = derived.height > 0 ? derived.height : result.height || 0;
|
|
78
|
+
const [tileW, tileH] = parseTileSize(result.group);
|
|
79
|
+
const resolvedSpriteUrl = spriteUrlTemplate
|
|
80
|
+
? spriteUrlTemplate.replace(/{group}/g, result.group).replace(/{size}/g, String(tileW))
|
|
81
|
+
: result.spriteUrl;
|
|
82
|
+
const cssOpts = {
|
|
83
|
+
prefix,
|
|
84
|
+
spriteUrlResolver: ({ spriteUrl }) => spriteUrl,
|
|
85
|
+
};
|
|
86
|
+
const lessText = (0, sprite_1.buildLessForSprite)({ group: result.group, spriteUrl: resolvedSpriteUrl, classes }, cssOpts);
|
|
87
|
+
return {
|
|
88
|
+
group: result.group,
|
|
89
|
+
kind: "png",
|
|
90
|
+
spriteUrl: resolvedSpriteUrl,
|
|
91
|
+
previewSpriteUrl: buildQuickPreviewUrl(localProjectId, result.group),
|
|
92
|
+
lessText,
|
|
93
|
+
status: "ok",
|
|
94
|
+
meta: {
|
|
95
|
+
mode: result.mode,
|
|
96
|
+
group: result.group,
|
|
97
|
+
tileWidth: tileW,
|
|
98
|
+
tileHeight: tileH,
|
|
99
|
+
spriteWidth,
|
|
100
|
+
spriteHeight,
|
|
101
|
+
classes,
|
|
102
|
+
},
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function deriveSpriteSize(classes) {
|
|
106
|
+
if (!classes.length)
|
|
107
|
+
return { width: 0, height: 0 };
|
|
108
|
+
let maxW = 0;
|
|
109
|
+
let maxH = 0;
|
|
110
|
+
for (const c of classes) {
|
|
111
|
+
const r = c.x + c.width;
|
|
112
|
+
const b = c.y + c.height;
|
|
113
|
+
if (r > maxW)
|
|
114
|
+
maxW = r;
|
|
115
|
+
if (b > maxH)
|
|
116
|
+
maxH = b;
|
|
117
|
+
}
|
|
118
|
+
return { width: maxW, height: maxH };
|
|
119
|
+
}
|
|
120
|
+
function parseTileSize(group) {
|
|
121
|
+
if (!group)
|
|
122
|
+
return [0, 0];
|
|
123
|
+
const parts = group.split("-");
|
|
124
|
+
if (parts.length === 0)
|
|
125
|
+
return [0, 0];
|
|
126
|
+
if (parts.length === 1) {
|
|
127
|
+
const n = parseInt(parts[0], 10);
|
|
128
|
+
return Number.isFinite(n) ? [n, n] : [0, 0];
|
|
129
|
+
}
|
|
130
|
+
const w = parseInt(parts[0], 10);
|
|
131
|
+
const h = parseInt(parts[1], 10);
|
|
132
|
+
return [Number.isFinite(w) ? w : 0, Number.isFinite(h) ? h : 0];
|
|
133
|
+
}
|
|
134
|
+
function mapQuickGroupsToSnapshot(projectId, results, remoteProj, localCfg) {
|
|
135
|
+
const cssPrefix = localCfg?.prefix ?? "sl";
|
|
136
|
+
const spriteUrlTpl = localCfg?.spriteUrl ?? "";
|
|
137
|
+
const groups = (results || []).map((r) => mapToGroup(r, projectId, cssPrefix, spriteUrlTpl));
|
|
138
|
+
return {
|
|
139
|
+
projectId,
|
|
140
|
+
sourceId: "",
|
|
141
|
+
iconsRoot: remoteProj?.iconsPath ?? "",
|
|
142
|
+
cacheOutDir: remoteProj?.exportSpritesDir ?? "",
|
|
143
|
+
config: {
|
|
144
|
+
projectId,
|
|
145
|
+
enabled: true,
|
|
146
|
+
sourceId: "",
|
|
147
|
+
localDir: "",
|
|
148
|
+
prefix: cssPrefix,
|
|
149
|
+
algorithm: "binary-tree",
|
|
150
|
+
persistLess: false,
|
|
151
|
+
updatedAt: remoteProj?.updatedAt
|
|
152
|
+
? new Date(remoteProj.updatedAt).getTime()
|
|
153
|
+
: Date.now(),
|
|
154
|
+
template: localCfg?.template ?? '<i class="{base} {class}"></i>',
|
|
155
|
+
spriteUrl: localCfg?.spriteUrl ?? "",
|
|
156
|
+
spriteExportDir: localCfg?.spriteExportDir ?? "",
|
|
157
|
+
lessExportDir: localCfg?.lessExportDir ?? "",
|
|
158
|
+
localImageRoot: localCfg?.localImageRoot ?? "",
|
|
159
|
+
localCacheDir: localCfg?.localCacheDir ?? "",
|
|
160
|
+
},
|
|
161
|
+
total: groups.length,
|
|
162
|
+
success: groups.length,
|
|
163
|
+
failed: 0,
|
|
164
|
+
groups,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
function copyRawResponseHeaders(response, reply) {
|
|
168
|
+
const contentType = response.headers.get("content-type");
|
|
169
|
+
if (contentType)
|
|
170
|
+
reply.header("content-type", contentType);
|
|
171
|
+
const contentLength = response.headers.get("content-length");
|
|
172
|
+
if (contentLength)
|
|
173
|
+
reply.header("content-length", contentLength);
|
|
174
|
+
const cacheControl = response.headers.get("cache-control");
|
|
175
|
+
if (cacheControl)
|
|
176
|
+
reply.header("cache-control", cacheControl);
|
|
177
|
+
const etag = response.headers.get("etag");
|
|
178
|
+
if (etag)
|
|
179
|
+
reply.header("etag", etag);
|
|
180
|
+
const lastModified = response.headers.get("last-modified");
|
|
181
|
+
if (lastModified)
|
|
182
|
+
reply.header("last-modified", lastModified);
|
|
183
|
+
}
|
|
184
|
+
async function hasQuickSprite(fastify, projectId) {
|
|
185
|
+
const cfg = await fastify.core.sprite.getConfig(projectId);
|
|
186
|
+
return !!cfg?.quickSpriteProjectId;
|
|
187
|
+
}
|
|
188
|
+
const miscCache = new Map();
|
|
189
|
+
const MISC_CACHE_TTL = 5 * 60 * 1000;
|
|
190
|
+
async function fetchAndCacheRemoteMiscImages(fastify, baseUrl, quickProjectId, forceRefresh = false) {
|
|
191
|
+
const cached = miscCache.get(quickProjectId);
|
|
192
|
+
if (!forceRefresh && cached && Date.now() - cached.time < MISC_CACHE_TTL) {
|
|
193
|
+
return cached.data;
|
|
194
|
+
}
|
|
195
|
+
const data = await quickFetch(fastify, baseUrl, `/api/misc/list?projectId=${encodeURIComponent(quickProjectId)}`);
|
|
196
|
+
miscCache.set(quickProjectId, { time: Date.now(), data });
|
|
197
|
+
return data;
|
|
198
|
+
}
|
|
199
|
+
function buildBrowseFromCache(quickProjectId, cache, dir) {
|
|
200
|
+
const list = cache.list || [];
|
|
201
|
+
const quickDir = dir ? `${dir}` : ".";
|
|
202
|
+
const filtered = list.filter((item) => item.dir === quickDir);
|
|
203
|
+
const sorted = [...filtered].sort((a, b) => a.name.localeCompare(b.name, "zh-Hans-CN", { numeric: true }));
|
|
204
|
+
const fileEntries = sorted.map((item) => {
|
|
205
|
+
const encodedName = encodeURIComponent(item.name);
|
|
206
|
+
return {
|
|
207
|
+
name: item.name,
|
|
208
|
+
kind: "file",
|
|
209
|
+
ext: item.name.split(".").pop()?.toLowerCase(),
|
|
210
|
+
url: `/api/sprite/misc-proxy/${encodeURIComponent(quickProjectId)}/${encodeURIComponent(item.dir)}/${encodedName}`,
|
|
211
|
+
};
|
|
212
|
+
});
|
|
213
|
+
const dirSet = new Set();
|
|
214
|
+
for (const item of list) {
|
|
215
|
+
if (item.dir)
|
|
216
|
+
dirSet.add(item.dir);
|
|
217
|
+
}
|
|
218
|
+
const subDirSet = new Set();
|
|
219
|
+
for (const d of dirSet) {
|
|
220
|
+
if (d === quickDir)
|
|
221
|
+
continue;
|
|
222
|
+
if (d.startsWith(quickDir) || quickDir === ".") {
|
|
223
|
+
const dirName = quickDir === "."
|
|
224
|
+
? d.split("/")[0]
|
|
225
|
+
: d.slice(quickDir.length).split("/")[1];
|
|
226
|
+
subDirSet.add(dirName);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
const dirEntries = Array.from(subDirSet)
|
|
230
|
+
.sort((a, b) => a.localeCompare(b, "zh-Hans-CN", { numeric: true }))
|
|
231
|
+
.map((d) => ({
|
|
232
|
+
name: d,
|
|
233
|
+
kind: "dir",
|
|
234
|
+
ext: undefined,
|
|
235
|
+
fileCount: list.filter((item) => item.dir === `${quickDir === "." ? "" : quickDir + "/"}${d}`).length,
|
|
236
|
+
}));
|
|
237
|
+
const entries = [...dirEntries, ...fileEntries];
|
|
238
|
+
return {
|
|
239
|
+
root: `remote:${quickProjectId}`,
|
|
240
|
+
dir,
|
|
241
|
+
entries,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
exports.MISC_PROXY_PREFIX = "/api/sprite/misc-proxy";
|
|
245
|
+
function buildRemoteMiscUrl(baseUrl, quickProjectId, filename) {
|
|
246
|
+
return `${baseUrl}/misc/${encodeURIComponent(quickProjectId)}/misc/${encodeURIComponent(filename)}`;
|
|
247
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
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_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_stream_1 = require("node:stream");
|
|
9
|
+
const errors_1 = require("@yinuo-ngm/errors");
|
|
10
|
+
const sprite_quick_utils_1 = require("./sprite-quick.utils");
|
|
11
|
+
function toSpriteConfigDto(cfg) {
|
|
12
|
+
return {
|
|
13
|
+
projectId: cfg.projectId,
|
|
14
|
+
enabled: cfg.enabled,
|
|
15
|
+
sourceId: cfg.sourceId,
|
|
16
|
+
localDir: cfg.localDir,
|
|
17
|
+
prefix: cfg.prefix,
|
|
18
|
+
template: cfg.template,
|
|
19
|
+
spriteUrl: cfg.spriteUrl,
|
|
20
|
+
spriteExportDir: cfg.spriteExportDir,
|
|
21
|
+
lessExportDir: cfg.lessExportDir,
|
|
22
|
+
algorithm: cfg.algorithm,
|
|
23
|
+
persistLess: cfg.persistLess,
|
|
24
|
+
updatedAt: cfg.updatedAt,
|
|
25
|
+
localImageRoot: cfg.localImageRoot,
|
|
26
|
+
localCacheDir: cfg.localCacheDir,
|
|
27
|
+
quickSpriteProjectId: cfg.quickSpriteProjectId,
|
|
28
|
+
quickSpriteEnabled: cfg.quickSpriteEnabled,
|
|
29
|
+
quickSpriteBaseUrl: cfg.quickSpriteBaseUrl,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function toSpriteGroupItemDto(item) {
|
|
33
|
+
return {
|
|
34
|
+
group: item.group,
|
|
35
|
+
kind: item.kind,
|
|
36
|
+
previewSpriteUrl: item.previewSpriteUrl,
|
|
37
|
+
spriteUrl: item.spriteUrl,
|
|
38
|
+
meta: item.meta,
|
|
39
|
+
lessText: item.lessText,
|
|
40
|
+
exported: item.exported,
|
|
41
|
+
status: item.status,
|
|
42
|
+
error: item.error,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function toSpriteSnapshotDto(snapshot) {
|
|
46
|
+
return {
|
|
47
|
+
projectId: snapshot.projectId,
|
|
48
|
+
sourceId: snapshot.sourceId,
|
|
49
|
+
iconsRoot: snapshot.iconsRoot,
|
|
50
|
+
cacheOutDir: snapshot.cacheOutDir,
|
|
51
|
+
config: toSpriteConfigDto(snapshot.config),
|
|
52
|
+
total: snapshot.total,
|
|
53
|
+
success: snapshot.success,
|
|
54
|
+
failed: snapshot.failed,
|
|
55
|
+
groups: (snapshot.groups ?? []).map(toSpriteGroupItemDto),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function toGenerateSpriteResultDto(snapshot) {
|
|
59
|
+
return toSpriteSnapshotDto(snapshot);
|
|
60
|
+
}
|
|
61
|
+
async function spriteRoutes(fastify) {
|
|
62
|
+
fastify.get("/config/:projectId", async (req) => {
|
|
63
|
+
const { projectId } = req.params;
|
|
64
|
+
const cfg = await fastify.core.sprite.getConfig(projectId);
|
|
65
|
+
if (cfg && !cfg?.quickSpriteBaseUrl) {
|
|
66
|
+
const base = (0, sprite_quick_utils_1.getBaseUrl)(cfg);
|
|
67
|
+
cfg.quickSpriteBaseUrl = base;
|
|
68
|
+
}
|
|
69
|
+
return cfg ? toSpriteConfigDto(cfg) : null;
|
|
70
|
+
});
|
|
71
|
+
fastify.post("/config/:projectId", async (req) => {
|
|
72
|
+
const { projectId } = req.params;
|
|
73
|
+
const body = req.body;
|
|
74
|
+
if (!body || !body.config) {
|
|
75
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, "Missing config in request body");
|
|
76
|
+
}
|
|
77
|
+
const nextCfg = body.config;
|
|
78
|
+
const nextAssets = (body.assets || {});
|
|
79
|
+
const hasLocalImageRoot = !!String(nextCfg.localImageRoot ?? "").trim();
|
|
80
|
+
const enableQuickSprite = nextCfg.quickSpriteProjectId && nextCfg.quickSpriteEnabled;
|
|
81
|
+
if (!enableQuickSprite && !nextAssets.iconsSvn && !hasLocalImageRoot) {
|
|
82
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, "iconsSvn asset or localImageRoot is required");
|
|
83
|
+
}
|
|
84
|
+
if (nextCfg.localDir && nextAssets.iconsSvn) {
|
|
85
|
+
nextAssets.iconsSvn.localDir = node_path_1.default.join(nextCfg.localDir, nextAssets.iconsSvn.label || "icons");
|
|
86
|
+
if (nextAssets.cutImageSvn) {
|
|
87
|
+
nextAssets.cutImageSvn.localDir = node_path_1.default.join(nextCfg.localDir, nextAssets.cutImageSvn.label || "images");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const shouldUpdateAssets = !!(nextAssets.iconsSvn || nextAssets.cutImageSvn);
|
|
91
|
+
const project = shouldUpdateAssets
|
|
92
|
+
? await fastify.core.project.updateAssets(projectId, nextAssets)
|
|
93
|
+
: await fastify.core.project.get(projectId);
|
|
94
|
+
if (project.assets?.iconsSvn) {
|
|
95
|
+
nextCfg.sourceId = project.assets.iconsSvn.id;
|
|
96
|
+
}
|
|
97
|
+
const cfg = await fastify.core.sprite.createConfig(projectId, nextCfg);
|
|
98
|
+
const assets = project.assets
|
|
99
|
+
? {
|
|
100
|
+
iconsSvn: project.assets.iconsSvn,
|
|
101
|
+
cutImageSvn: project.assets.cutImageSvn,
|
|
102
|
+
}
|
|
103
|
+
: undefined;
|
|
104
|
+
return {
|
|
105
|
+
cfg: toSpriteConfigDto(cfg),
|
|
106
|
+
project: { id: project.id, name: project.name, root: project.root, assets },
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
fastify.post("/generate/:projectId", async (req) => {
|
|
110
|
+
const { projectId } = req.params;
|
|
111
|
+
const body = req.body || {};
|
|
112
|
+
const quickProjectId = await (0, sprite_quick_utils_1.resolveEnabledRemoteProjectId)(fastify, projectId);
|
|
113
|
+
if (quickProjectId) {
|
|
114
|
+
const localCfg = await fastify.core.sprite.getConfig(projectId);
|
|
115
|
+
const baseUrl = (0, sprite_quick_utils_1.getBaseUrl)(localCfg);
|
|
116
|
+
const [results, remoteProj] = await Promise.all([
|
|
117
|
+
(0, sprite_quick_utils_1.quickFetch)(fastify, baseUrl, `/api/project-sprites?projectId=${encodeURIComponent(quickProjectId)}`),
|
|
118
|
+
(0, sprite_quick_utils_1.fetchRemoteProject)(fastify, baseUrl, quickProjectId),
|
|
119
|
+
]);
|
|
120
|
+
if (!results?.length) {
|
|
121
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `远端项目「${quickProjectId}」尚未生成任何雪碧图,请先在远端服务中为该项目生成雪碧图后再试`);
|
|
122
|
+
}
|
|
123
|
+
return (0, sprite_quick_utils_1.mapQuickGroupsToSnapshot)(projectId, results, remoteProj, localCfg);
|
|
124
|
+
}
|
|
125
|
+
const result = await fastify.core.sprite.generate(projectId, {
|
|
126
|
+
groups: body.groups,
|
|
127
|
+
forceRefresh: !!body.forceRefresh,
|
|
128
|
+
concurrency: body.concurrency ?? 1,
|
|
129
|
+
continueOnError: body.continueOnError ?? true,
|
|
130
|
+
});
|
|
131
|
+
return toGenerateSpriteResultDto(result);
|
|
132
|
+
});
|
|
133
|
+
fastify.get("/list/:projectId", async (req) => {
|
|
134
|
+
const { projectId } = req.params;
|
|
135
|
+
const local = String(req.query?.local ?? "").toLowerCase() === "true";
|
|
136
|
+
const quickProjectId = await (0, sprite_quick_utils_1.resolveEnabledRemoteProjectId)(fastify, projectId);
|
|
137
|
+
if (quickProjectId) {
|
|
138
|
+
const localCfg = await fastify.core.sprite.getConfig(projectId);
|
|
139
|
+
const baseUrl = (0, sprite_quick_utils_1.getBaseUrl)(localCfg);
|
|
140
|
+
const [results, remoteProj] = await Promise.all([
|
|
141
|
+
(0, sprite_quick_utils_1.quickFetch)(fastify, baseUrl, `/api/project-sprites?projectId=${encodeURIComponent(quickProjectId)}`),
|
|
142
|
+
(0, sprite_quick_utils_1.fetchRemoteProject)(fastify, baseUrl, quickProjectId),
|
|
143
|
+
]);
|
|
144
|
+
return (0, sprite_quick_utils_1.mapQuickGroupsToSnapshot)(projectId, results, remoteProj, localCfg);
|
|
145
|
+
}
|
|
146
|
+
const snapshot = await fastify.core.sprite.getSprites(projectId, local);
|
|
147
|
+
return toSpriteSnapshotDto(snapshot);
|
|
148
|
+
});
|
|
149
|
+
fastify.get("/quick/projects", async (_req) => {
|
|
150
|
+
const baseUrl = (0, sprite_quick_utils_1.getBaseUrl)();
|
|
151
|
+
const projects = await (0, sprite_quick_utils_1.quickFetch)(fastify, baseUrl, "/api/projects");
|
|
152
|
+
return projects;
|
|
153
|
+
});
|
|
154
|
+
fastify.get("/quick/groups/:projectId", async (req) => {
|
|
155
|
+
const { projectId } = req.params;
|
|
156
|
+
const baseUrl = (0, sprite_quick_utils_1.getBaseUrl)();
|
|
157
|
+
const groups = await (0, sprite_quick_utils_1.quickFetch)(fastify, baseUrl, `/api/groups?projectId=${encodeURIComponent(projectId)}`);
|
|
158
|
+
return groups;
|
|
159
|
+
});
|
|
160
|
+
fastify.get("/proxy/:projectId/:group.png", async (req, reply) => {
|
|
161
|
+
const { projectId, group } = req.params;
|
|
162
|
+
const cfg = await fastify.core.sprite.getConfig(projectId);
|
|
163
|
+
const quickProjectId = cfg?.quickSpriteProjectId;
|
|
164
|
+
if (!quickProjectId) {
|
|
165
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `项目「${projectId}」未配置快捷雪碧图远端映射`);
|
|
166
|
+
}
|
|
167
|
+
const baseUrl = (0, sprite_quick_utils_1.getBaseUrl)(cfg);
|
|
168
|
+
const remoteUrl = `${baseUrl}/sprites/${encodeURIComponent(quickProjectId)}/${encodeURIComponent(group)}.png`;
|
|
169
|
+
fastify.log.info(`[sprite-proxy] → GET ${remoteUrl}`);
|
|
170
|
+
let response;
|
|
171
|
+
try {
|
|
172
|
+
response = await fetch(remoteUrl);
|
|
173
|
+
}
|
|
174
|
+
catch (err) {
|
|
175
|
+
fastify.log.error(`[sprite-proxy] ✗ ${remoteUrl}: ${err?.message || err}`);
|
|
176
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.INTERNAL_ERROR, `无法连接远端雪碧图服务: ${err?.message || err}`);
|
|
177
|
+
}
|
|
178
|
+
if (!response.ok) {
|
|
179
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `远端雪碧图不存在: ${response.status}`);
|
|
180
|
+
}
|
|
181
|
+
(0, sprite_quick_utils_1.copyRawResponseHeaders)(response, reply);
|
|
182
|
+
const body = response.body;
|
|
183
|
+
if (!body) {
|
|
184
|
+
return reply.status(response.status).send();
|
|
185
|
+
}
|
|
186
|
+
return reply.status(response.status).send(node_stream_1.Readable.fromWeb(body));
|
|
187
|
+
});
|
|
188
|
+
fastify.get("/misc-proxy/:quickProjectId/*", async (req, reply) => {
|
|
189
|
+
const { quickProjectId } = req.params;
|
|
190
|
+
const filename = req.params["*"];
|
|
191
|
+
const baseUrl = (0, sprite_quick_utils_1.getBaseUrl)();
|
|
192
|
+
const remoteUrl = (0, sprite_quick_utils_1.buildRemoteMiscUrl)(baseUrl, quickProjectId, filename);
|
|
193
|
+
fastify.log.info(`[sprite-misc-proxy] → GET ${remoteUrl}`);
|
|
194
|
+
let response;
|
|
195
|
+
try {
|
|
196
|
+
response = await fetch(remoteUrl);
|
|
197
|
+
}
|
|
198
|
+
catch (err) {
|
|
199
|
+
fastify.log.error(`[sprite-misc-proxy] ✗ ${remoteUrl}: ${err?.message || err}`);
|
|
200
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.INTERNAL_ERROR, `无法连接远端切图服务: ${err?.message || err}`);
|
|
201
|
+
}
|
|
202
|
+
if (!response.ok) {
|
|
203
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.NOT_FOUND, `远端切图不存在: ${response.status}`);
|
|
204
|
+
}
|
|
205
|
+
(0, sprite_quick_utils_1.copyRawResponseHeaders)(response, reply);
|
|
206
|
+
const body = response.body;
|
|
207
|
+
if (!body) {
|
|
208
|
+
return reply.status(response.status).send();
|
|
209
|
+
}
|
|
210
|
+
return reply.status(response.status).send(node_stream_1.Readable.fromWeb(body));
|
|
211
|
+
});
|
|
212
|
+
}
|
|
@@ -31,7 +31,7 @@ function listDir(root) {
|
|
|
31
31
|
.filter(d => !SKIP.has(d.name) && !d.name.startsWith("."))
|
|
32
32
|
.map(d => ({
|
|
33
33
|
name: d.name,
|
|
34
|
-
kind: d.isDirectory() ? "dir" : "file",
|
|
34
|
+
kind: (d.isDirectory() ? "dir" : "file"),
|
|
35
35
|
ext: d.isDirectory() ? undefined : node_path_1.default.extname(d.name).toLowerCase(),
|
|
36
36
|
})).sort((a, b) => {
|
|
37
37
|
if (a.kind === b.kind) {
|
|
@@ -45,6 +45,12 @@ function countFiles(dir) {
|
|
|
45
45
|
return 0;
|
|
46
46
|
return node_fs_1.default.readdirSync(dir, { withFileTypes: true }).filter(d => d.isFile()).length;
|
|
47
47
|
}
|
|
48
|
+
function toBrowseEntriesDto(root, entries) {
|
|
49
|
+
return { root, entries };
|
|
50
|
+
}
|
|
51
|
+
function toBrowseFilesDto(root, dir, entries) {
|
|
52
|
+
return { root, dir, entries };
|
|
53
|
+
}
|
|
48
54
|
async function spriteBrowseRoutes(fastify) {
|
|
49
55
|
fastify.get("/icons/groups/:projectId", async (req) => {
|
|
50
56
|
const { projectId } = req.params;
|
|
@@ -53,7 +59,7 @@ async function spriteBrowseRoutes(fastify) {
|
|
|
53
59
|
const localRoot = String(cfg?.localImageRoot ?? "").trim();
|
|
54
60
|
const root = localRoot || project?.assets?.iconsSvn?.localDir;
|
|
55
61
|
if (!root) {
|
|
56
|
-
return
|
|
62
|
+
return toBrowseEntriesDto("", []);
|
|
57
63
|
}
|
|
58
64
|
const entries = listDir(root).filter(e => e.kind === "dir");
|
|
59
65
|
if (localRoot) {
|
|
@@ -62,7 +68,7 @@ async function spriteBrowseRoutes(fastify) {
|
|
|
62
68
|
entries.unshift({ name: "root", kind: "dir", ext: undefined });
|
|
63
69
|
}
|
|
64
70
|
}
|
|
65
|
-
return
|
|
71
|
+
return toBrowseEntriesDto(root, entries);
|
|
66
72
|
});
|
|
67
73
|
fastify.get("/icons/files/:projectId", async (req) => {
|
|
68
74
|
const { projectId } = req.params;
|
|
@@ -72,10 +78,10 @@ async function spriteBrowseRoutes(fastify) {
|
|
|
72
78
|
const localRoot = String(cfg?.localImageRoot ?? "").trim();
|
|
73
79
|
const root = localRoot || project?.assets?.iconsSvn?.localDir;
|
|
74
80
|
if (!root) {
|
|
75
|
-
return
|
|
81
|
+
return toBrowseEntriesDto("", []);
|
|
76
82
|
}
|
|
77
83
|
const isRootGroup = !!localRoot && (group === "root");
|
|
78
|
-
const groupDir = isRootGroup ? root : safeJoin(root, group ||
|
|
84
|
+
const groupDir = isRootGroup ? root : safeJoin(root, group || "");
|
|
79
85
|
const entries = listDir(groupDir)
|
|
80
86
|
.filter(e => e.kind === "file")
|
|
81
87
|
.map(e => ({
|
|
@@ -84,22 +90,22 @@ async function spriteBrowseRoutes(fastify) {
|
|
|
84
90
|
? `/api/static/local/${projectId}/${isRootGroup ? e.name : `${group}/${e.name}`}`
|
|
85
91
|
: `/api/static/svn/${projectId}/icons/${group}/${e.name}`,
|
|
86
92
|
}));
|
|
87
|
-
return
|
|
93
|
+
return toBrowseEntriesDto(groupDir, entries);
|
|
88
94
|
});
|
|
89
95
|
fastify.get("/images/list/:projectId", async (req) => {
|
|
90
96
|
const { projectId } = req.params;
|
|
91
97
|
const project = await fastify.core.project.get(projectId);
|
|
92
98
|
const root = project?.assets?.cutImageSvn?.localDir;
|
|
93
99
|
if (!root) {
|
|
94
|
-
return
|
|
100
|
+
return toBrowseEntriesDto("", []);
|
|
95
101
|
}
|
|
96
102
|
const dir = String(req.query?.dir ?? "").trim();
|
|
97
103
|
if (dir.split(/[\\/]/g).some(seg => seg === "..")) {
|
|
98
|
-
return
|
|
104
|
+
return toBrowseFilesDto(root, "", []);
|
|
99
105
|
}
|
|
100
106
|
const absDir = dir ? safeJoin(root, dir) : root;
|
|
101
107
|
if (!node_fs_1.default.existsSync(absDir))
|
|
102
|
-
return
|
|
108
|
+
return toBrowseFilesDto(root, dir, []);
|
|
103
109
|
const entries = listDir(absDir).map(e => {
|
|
104
110
|
if (e.kind === "file") {
|
|
105
111
|
const rel = dir ? `${dir}/${e.name}` : e.name;
|
|
@@ -112,11 +118,11 @@ async function spriteBrowseRoutes(fastify) {
|
|
|
112
118
|
const rel = dir ? `${dir}/${e.name}` : e.name;
|
|
113
119
|
return {
|
|
114
120
|
...e,
|
|
115
|
-
fileCount: countFiles(safeJoin(root, rel))
|
|
121
|
+
fileCount: countFiles(safeJoin(root, rel)),
|
|
116
122
|
};
|
|
117
123
|
}
|
|
118
124
|
return e;
|
|
119
125
|
});
|
|
120
|
-
return
|
|
126
|
+
return toBrowseFilesDto(root, dir, entries);
|
|
121
127
|
});
|
|
122
128
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { FastifyInstance } from "fastify";
|
|
1
|
+
import type { FastifyInstance } from "fastify";
|
|
2
2
|
export declare function spriteRoutes(fastify: FastifyInstance): Promise<void>;
|
|
@@ -6,27 +6,75 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.spriteRoutes = spriteRoutes;
|
|
7
7
|
const node_path_1 = __importDefault(require("node:path"));
|
|
8
8
|
const errors_1 = require("@yinuo-ngm/errors");
|
|
9
|
+
function toSpriteConfigDto(cfg) {
|
|
10
|
+
return {
|
|
11
|
+
projectId: cfg.projectId,
|
|
12
|
+
enabled: cfg.enabled,
|
|
13
|
+
sourceId: cfg.sourceId,
|
|
14
|
+
localDir: cfg.localDir,
|
|
15
|
+
prefix: cfg.prefix,
|
|
16
|
+
template: cfg.template,
|
|
17
|
+
spriteUrl: cfg.spriteUrl,
|
|
18
|
+
spriteExportDir: cfg.spriteExportDir,
|
|
19
|
+
lessExportDir: cfg.lessExportDir,
|
|
20
|
+
algorithm: cfg.algorithm,
|
|
21
|
+
persistLess: cfg.persistLess,
|
|
22
|
+
updatedAt: cfg.updatedAt,
|
|
23
|
+
localImageRoot: cfg.localImageRoot,
|
|
24
|
+
localCacheDir: cfg.localCacheDir,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function toSpriteGroupItemDto(item) {
|
|
28
|
+
return {
|
|
29
|
+
group: item.group,
|
|
30
|
+
kind: item.kind,
|
|
31
|
+
previewSpriteUrl: item.previewSpriteUrl,
|
|
32
|
+
spriteUrl: item.spriteUrl,
|
|
33
|
+
meta: item.meta,
|
|
34
|
+
lessText: item.lessText,
|
|
35
|
+
exported: item.exported,
|
|
36
|
+
status: item.status,
|
|
37
|
+
error: item.error,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function toSpriteSnapshotDto(snapshot) {
|
|
41
|
+
return {
|
|
42
|
+
projectId: snapshot.projectId,
|
|
43
|
+
sourceId: snapshot.sourceId,
|
|
44
|
+
iconsRoot: snapshot.iconsRoot,
|
|
45
|
+
cacheOutDir: snapshot.cacheOutDir,
|
|
46
|
+
config: toSpriteConfigDto(snapshot.config),
|
|
47
|
+
total: snapshot.total,
|
|
48
|
+
success: snapshot.success,
|
|
49
|
+
failed: snapshot.failed,
|
|
50
|
+
groups: (snapshot.groups ?? []).map(toSpriteGroupItemDto),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function toGenerateSpriteResultDto(snapshot) {
|
|
54
|
+
return toSpriteSnapshotDto(snapshot);
|
|
55
|
+
}
|
|
9
56
|
async function spriteRoutes(fastify) {
|
|
10
57
|
fastify.get("/config/:projectId", async (req) => {
|
|
11
58
|
const { projectId } = req.params;
|
|
12
|
-
|
|
59
|
+
const cfg = await fastify.core.sprite.getConfig(projectId);
|
|
60
|
+
return cfg ? toSpriteConfigDto(cfg) : null;
|
|
13
61
|
});
|
|
14
62
|
fastify.post("/config/:projectId", async (req) => {
|
|
15
63
|
const { projectId } = req.params;
|
|
16
64
|
const body = req.body;
|
|
17
65
|
if (!body || !body.config) {
|
|
18
|
-
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST,
|
|
66
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, "Missing config in request body");
|
|
19
67
|
}
|
|
20
68
|
const nextCfg = body.config;
|
|
21
|
-
const nextAssets = body.assets || {};
|
|
69
|
+
const nextAssets = (body.assets || {});
|
|
22
70
|
const hasLocalImageRoot = !!String(nextCfg.localImageRoot ?? "").trim();
|
|
23
71
|
if (!nextAssets.iconsSvn && !hasLocalImageRoot) {
|
|
24
|
-
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST,
|
|
72
|
+
throw new errors_1.GlobalError(errors_1.GlobalErrorCodes.BAD_REQUEST, "iconsSvn asset or localImageRoot is required");
|
|
25
73
|
}
|
|
26
74
|
if (nextCfg.localDir && nextAssets.iconsSvn) {
|
|
27
|
-
nextAssets.iconsSvn.localDir = node_path_1.default.join(nextCfg.localDir, nextAssets.iconsSvn.label ||
|
|
75
|
+
nextAssets.iconsSvn.localDir = node_path_1.default.join(nextCfg.localDir, nextAssets.iconsSvn.label || "icons");
|
|
28
76
|
if (nextAssets.cutImageSvn) {
|
|
29
|
-
nextAssets.cutImageSvn.localDir = node_path_1.default.join(nextCfg.localDir, nextAssets.cutImageSvn.label ||
|
|
77
|
+
nextAssets.cutImageSvn.localDir = node_path_1.default.join(nextCfg.localDir, nextAssets.cutImageSvn.label || "images");
|
|
30
78
|
}
|
|
31
79
|
}
|
|
32
80
|
const shouldUpdateAssets = !!(nextAssets.iconsSvn || nextAssets.cutImageSvn);
|
|
@@ -37,7 +85,16 @@ async function spriteRoutes(fastify) {
|
|
|
37
85
|
nextCfg.sourceId = project.assets.iconsSvn.id;
|
|
38
86
|
}
|
|
39
87
|
const cfg = await fastify.core.sprite.createConfig(projectId, nextCfg);
|
|
40
|
-
|
|
88
|
+
const assets = project.assets
|
|
89
|
+
? {
|
|
90
|
+
iconsSvn: project.assets.iconsSvn,
|
|
91
|
+
cutImageSvn: project.assets.cutImageSvn,
|
|
92
|
+
}
|
|
93
|
+
: undefined;
|
|
94
|
+
return {
|
|
95
|
+
cfg: toSpriteConfigDto(cfg),
|
|
96
|
+
project: { id: project.id, name: project.name, root: project.root, assets },
|
|
97
|
+
};
|
|
41
98
|
});
|
|
42
99
|
fastify.post("/generate/:projectId", async (req) => {
|
|
43
100
|
const { projectId } = req.params;
|
|
@@ -48,12 +105,12 @@ async function spriteRoutes(fastify) {
|
|
|
48
105
|
concurrency: body.concurrency ?? 1,
|
|
49
106
|
continueOnError: body.continueOnError ?? true,
|
|
50
107
|
});
|
|
51
|
-
return result;
|
|
108
|
+
return toGenerateSpriteResultDto(result);
|
|
52
109
|
});
|
|
53
110
|
fastify.get("/list/:projectId", async (req) => {
|
|
54
111
|
const { projectId } = req.params;
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
return
|
|
112
|
+
const local = String(req.query?.local ?? "").toLowerCase() === "true";
|
|
113
|
+
const snapshot = await fastify.core.sprite.getSprites(projectId, local);
|
|
114
|
+
return toSpriteSnapshotDto(snapshot);
|
|
58
115
|
});
|
|
59
116
|
}
|