@dsh-plus/image-studio 0.1.18 → 0.1.19

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/index.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { Service } from "@deepseek-ai/cordis";
2
2
  import { credentialRef } from "@deepseek-ai/dsh-credentials";
3
- import { pluginDataPath, unwrapVolatile } from "@dsh-plus/shared";
3
+ import { atomicWriteFile, commitTmpFile, pluginDataPath, unwrapVolatile } from "@dsh-plus/shared";
4
4
  import { request } from "node:http";
5
5
  import { request as request$1 } from "node:https";
6
6
  import { HttpsProxyAgent } from "https-proxy-agent";
7
7
  import { randomUUID } from "node:crypto";
8
- import { appendFile, mkdir, readFile, readdir, rename, rm, writeFile } from "node:fs/promises";
8
+ import { appendFile, mkdir, readFile, readdir, rm, writeFile } from "node:fs/promises";
9
9
  import { join } from "node:path";
10
10
  import z from "@deepseek-ai/schemastery";
11
11
  //#region src/errors.ts
@@ -1068,7 +1068,7 @@ async function saveGalleryItem(input) {
1068
1068
  const target = imagePathOf(imageId, extOfMime(image.mime));
1069
1069
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
1070
1070
  await writeFile(tmp, image.data);
1071
- await rename(tmp, target);
1071
+ await commitTmpFile(tmp, target);
1072
1072
  imageIds.push(imageId);
1073
1073
  }
1074
1074
  const item = {
@@ -1091,9 +1091,7 @@ async function deleteGalleryItem(itemId) {
1091
1091
  for (const name of files) if (name.startsWith(`${imageId}.`)) await rm(join(imagesDir(), name), { force: true });
1092
1092
  }
1093
1093
  const kept = items.filter((item) => item.id !== itemId);
1094
- const tmp = `${indexFile$1()}.tmp-${process.pid}-${Date.now()}`;
1095
- await writeFile(tmp, kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""), "utf8");
1096
- await rename(tmp, indexFile$1());
1094
+ await atomicWriteFile(indexFile$1(), kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""));
1097
1095
  return true;
1098
1096
  }
1099
1097
  //#endregion
@@ -1296,7 +1294,7 @@ async function saveUpload(input) {
1296
1294
  const target = blobPathOf(id, ext);
1297
1295
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`;
1298
1296
  await writeFile(tmp, input.data);
1299
- await rename(tmp, target);
1297
+ await commitTmpFile(tmp, target);
1300
1298
  const entry = {
1301
1299
  id,
1302
1300
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -1325,9 +1323,7 @@ async function removeUpload(entry) {
1325
1323
  }
1326
1324
  /** 索引导出为 JSONL(重写式删除的公共收尾)。 */
1327
1325
  async function rewriteIndex(kept) {
1328
- const tmp = `${indexFile()}.tmp-${process.pid}-${Date.now()}`;
1329
- await writeFile(tmp, kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""), "utf8");
1330
- await rename(tmp, indexFile());
1326
+ await atomicWriteFile(indexFile(), kept.map((item) => JSON.stringify(item)).join("\n") + (kept.length > 0 ? "\n" : ""));
1331
1327
  }
1332
1328
  /**
1333
1329
  * 回收孤儿上传:未被 keepIds 引用且创建时间早于 ttlMs 的条目删除。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-plus/image-studio",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "dsh-plus service+ui plugin: 图像工作室——OpenAI Images 协议文生图/图生图,全参数开关化,双预设体系,并发生图任务与可二次编辑画廊",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -20,7 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "https-proxy-agent": "^9.1.0",
23
- "@dsh-plus/shared": "0.1.25"
23
+ "@dsh-plus/shared": "0.1.27"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@deepseek-ai/cordis": "^4.0.4",
@@ -7,10 +7,10 @@
7
7
  */
8
8
 
9
9
  import { randomUUID } from 'node:crypto'
10
- import { appendFile, mkdir, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises'
10
+ import { appendFile, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'
11
11
  import { join } from 'node:path'
12
12
 
13
- import { pluginDataPath } from '@dsh-plus/shared'
13
+ import { atomicWriteFile, commitTmpFile, pluginDataPath } from '@dsh-plus/shared'
14
14
  import { isImageId } from '../images/id.ts'
15
15
  import { extOfMime } from '../images/mime.ts'
16
16
  import type { ImageEndpoint } from '../provider/types.ts'
@@ -121,11 +121,12 @@ export async function saveGalleryItem(input: {
121
121
  for (const image of input.images) {
122
122
  const imageId = randomUUID()
123
123
  const ext = extOfMime(image.mime)
124
- // 原子写:临时文件 + rename,中断不留半截图片。
124
+ // 图片是字节(官方 writeFileAtomic 仅收字符串):tmp 落盘 + commitTmpFile
125
+ // rename 提交,rename 被占用时回退复制,中断不留半截图片。
125
126
  const target = imagePathOf(imageId, ext)
126
127
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`
127
128
  await writeFile(tmp, image.data)
128
- await rename(tmp, target)
129
+ await commitTmpFile(tmp, target)
129
130
  imageIds.push(imageId)
130
131
  }
131
132
  const item: GalleryItem = {
@@ -153,13 +154,10 @@ export async function deleteGalleryItem(itemId: string): Promise<boolean> {
153
154
  }
154
155
  }
155
156
  const kept = items.filter((item) => item.id !== itemId)
156
- const tmp = `${indexFile()}.tmp-${process.pid}-${Date.now()}`
157
- await writeFile(
158
- tmp,
157
+ await atomicWriteFile(
158
+ indexFile(),
159
159
  kept.map((item) => JSON.stringify(item)).join('\n') + (kept.length > 0 ? '\n' : ''),
160
- 'utf8',
161
160
  )
162
- await rename(tmp, indexFile())
163
161
  return true
164
162
  }
165
163
 
@@ -8,10 +8,10 @@
8
8
  */
9
9
 
10
10
  import { randomUUID } from 'node:crypto'
11
- import { appendFile, mkdir, readdir, readFile, rename, rm, writeFile } from 'node:fs/promises'
11
+ import { appendFile, mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises'
12
12
  import { join } from 'node:path'
13
13
 
14
- import { pluginDataPath } from '@dsh-plus/shared'
14
+ import { atomicWriteFile, commitTmpFile, pluginDataPath } from '@dsh-plus/shared'
15
15
  import { isImageId } from '../images/id.ts'
16
16
  import { extOfMime } from '../images/mime.ts'
17
17
 
@@ -96,9 +96,10 @@ export async function saveUpload(input: {
96
96
  const id = randomUUID()
97
97
  const ext = extOfMime(input.mime)
98
98
  const target = blobPathOf(id, ext)
99
+ // 字节走 tmp + commitTmpFile(官方 writeFileAtomic 仅收字符串)。
99
100
  const tmp = `${target}.tmp-${process.pid}-${Date.now()}`
100
101
  await writeFile(tmp, input.data)
101
- await rename(tmp, target)
102
+ await commitTmpFile(tmp, target)
102
103
  const entry: UploadEntry = {
103
104
  id,
104
105
  createdAt: new Date().toISOString(),
@@ -128,13 +129,10 @@ async function removeUpload(entry: UploadEntry): Promise<void> {
128
129
 
129
130
  /** 索引导出为 JSONL(重写式删除的公共收尾)。 */
130
131
  async function rewriteIndex(kept: UploadEntry[]): Promise<void> {
131
- const tmp = `${indexFile()}.tmp-${process.pid}-${Date.now()}`
132
- await writeFile(
133
- tmp,
132
+ await atomicWriteFile(
133
+ indexFile(),
134
134
  kept.map((item) => JSON.stringify(item)).join('\n') + (kept.length > 0 ? '\n' : ''),
135
- 'utf8',
136
135
  )
137
- await rename(tmp, indexFile())
138
136
  }
139
137
 
140
138
  /**