@zlooks.cn/images-server 1.0.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/dist/assets/provider.d.ts +3 -0
- package/dist/assets/provider.d.ts.map +1 -0
- package/dist/assets/provider.js +6 -0
- package/dist/assets/provider.js.map +1 -0
- package/dist/assets/read-image-asset.d.ts +5 -0
- package/dist/assets/read-image-asset.d.ts.map +1 -0
- package/dist/assets/read-image-asset.js +88 -0
- package/dist/assets/read-image-asset.js.map +1 -0
- package/dist/assets/response-policy.d.ts +6 -0
- package/dist/assets/response-policy.d.ts.map +1 -0
- package/dist/assets/response-policy.js +49 -0
- package/dist/assets/response-policy.js.map +1 -0
- package/dist/caches/public-image-cache.d.ts +18 -0
- package/dist/caches/public-image-cache.d.ts.map +1 -0
- package/dist/caches/public-image-cache.js +58 -0
- package/dist/caches/public-image-cache.js.map +1 -0
- package/dist/command/index.d.ts +3 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.js +23 -0
- package/dist/command/index.js.map +1 -0
- package/dist/domain/image-error.d.ts +5 -0
- package/dist/domain/image-error.d.ts.map +1 -0
- package/dist/domain/image-error.js +9 -0
- package/dist/domain/image-error.js.map +1 -0
- package/dist/domain/list-cursor.d.ts +10 -0
- package/dist/domain/list-cursor.d.ts.map +1 -0
- package/dist/domain/list-cursor.js +31 -0
- package/dist/domain/list-cursor.js.map +1 -0
- package/dist/domain/output-schema.d.ts +63 -0
- package/dist/domain/output-schema.d.ts.map +1 -0
- package/dist/domain/output-schema.js +25 -0
- package/dist/domain/output-schema.js.map +1 -0
- package/dist/domain/schema.d.ts +69 -0
- package/dist/domain/schema.d.ts.map +1 -0
- package/dist/domain/schema.js +44 -0
- package/dist/domain/schema.js.map +1 -0
- package/dist/identity.d.ts +3 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +3 -0
- package/dist/identity.js.map +1 -0
- package/dist/mcp/provider.d.ts +2 -0
- package/dist/mcp/provider.d.ts.map +1 -0
- package/dist/mcp/provider.js +96 -0
- package/dist/mcp/provider.js.map +1 -0
- package/dist/messages/public-asset/read.msg.d.ts +3 -0
- package/dist/messages/public-asset/read.msg.d.ts.map +1 -0
- package/dist/messages/public-asset/read.msg.js +10 -0
- package/dist/messages/public-asset/read.msg.js.map +1 -0
- package/dist/migrations/index.d.ts +3 -0
- package/dist/migrations/index.d.ts.map +1 -0
- package/dist/migrations/index.js +3 -0
- package/dist/migrations/index.js.map +1 -0
- package/dist/models/delete-image.model.d.ts +21 -0
- package/dist/models/delete-image.model.d.ts.map +1 -0
- package/dist/models/delete-image.model.js +36 -0
- package/dist/models/delete-image.model.js.map +1 -0
- package/dist/models/list-image.model.d.ts +21 -0
- package/dist/models/list-image.model.d.ts.map +1 -0
- package/dist/models/list-image.model.js +15 -0
- package/dist/models/list-image.model.js.map +1 -0
- package/dist/models/read-image.model.d.ts +20 -0
- package/dist/models/read-image.model.d.ts.map +1 -0
- package/dist/models/read-image.model.js +15 -0
- package/dist/models/read-image.model.js.map +1 -0
- package/dist/models/upload-image.model.d.ts +22 -0
- package/dist/models/upload-image.model.d.ts.map +1 -0
- package/dist/models/upload-image.model.js +52 -0
- package/dist/models/upload-image.model.js.map +1 -0
- package/dist/persistence/entities.d.ts +22 -0
- package/dist/persistence/entities.d.ts.map +1 -0
- package/dist/persistence/entities.js +20 -0
- package/dist/persistence/entities.js.map +1 -0
- package/dist/persistence/image-query.d.ts +5 -0
- package/dist/persistence/image-query.d.ts.map +1 -0
- package/dist/persistence/image-query.js +44 -0
- package/dist/persistence/image-query.js.map +1 -0
- package/dist/persistence/image-store.d.ts +30 -0
- package/dist/persistence/image-store.d.ts.map +1 -0
- package/dist/persistence/image-store.js +63 -0
- package/dist/persistence/image-store.js.map +1 -0
- package/dist/presentation/image-projection.d.ts +24 -0
- package/dist/presentation/image-projection.d.ts.map +1 -0
- package/dist/presentation/image-projection.js +19 -0
- package/dist/presentation/image-projection.js.map +1 -0
- package/dist/runtime/recover-images.d.ts +5 -0
- package/dist/runtime/recover-images.d.ts.map +1 -0
- package/dist/runtime/recover-images.js +21 -0
- package/dist/runtime/recover-images.js.map +1 -0
- package/dist/services/application.service.d.ts +4 -0
- package/dist/services/application.service.d.ts.map +1 -0
- package/dist/services/application.service.js +22 -0
- package/dist/services/application.service.js.map +1 -0
- package/dist/services/config.service.d.ts +25 -0
- package/dist/services/config.service.d.ts.map +1 -0
- package/dist/services/config.service.js +19 -0
- package/dist/services/config.service.js.map +1 -0
- package/dist/services/database.service.d.ts +3 -0
- package/dist/services/database.service.d.ts.map +1 -0
- package/dist/services/database.service.js +23 -0
- package/dist/services/database.service.js.map +1 -0
- package/dist/services/images-runtime.service.d.ts +9 -0
- package/dist/services/images-runtime.service.d.ts.map +1 -0
- package/dist/services/images-runtime.service.js +16 -0
- package/dist/services/images-runtime.service.js.map +1 -0
- package/dist/services/images.boot.d.ts +3 -0
- package/dist/services/images.boot.d.ts.map +1 -0
- package/dist/services/images.boot.js +8 -0
- package/dist/services/images.boot.js.map +1 -0
- package/dist/services/logger.service.d.ts +4 -0
- package/dist/services/logger.service.d.ts.map +1 -0
- package/dist/services/logger.service.js +8 -0
- package/dist/services/logger.service.js.map +1 -0
- package/dist/services/mcp-provider.service.d.ts +3 -0
- package/dist/services/mcp-provider.service.d.ts.map +1 -0
- package/dist/services/mcp-provider.service.js +15 -0
- package/dist/services/mcp-provider.service.js.map +1 -0
- package/dist/services/public-assets.service.d.ts +4 -0
- package/dist/services/public-assets.service.d.ts.map +1 -0
- package/dist/services/public-assets.service.js +15 -0
- package/dist/services/public-assets.service.js.map +1 -0
- package/dist/services/redis.service.d.ts +3 -0
- package/dist/services/redis.service.d.ts.map +1 -0
- package/dist/services/redis.service.js +35 -0
- package/dist/services/redis.service.js.map +1 -0
- package/dist/storage/image-path.d.ts +3 -0
- package/dist/storage/image-path.d.ts.map +1 -0
- package/dist/storage/image-path.js +17 -0
- package/dist/storage/image-path.js.map +1 -0
- package/dist/storage/inspect-image.d.ts +9 -0
- package/dist/storage/inspect-image.d.ts.map +1 -0
- package/dist/storage/inspect-image.js +36 -0
- package/dist/storage/inspect-image.js.map +1 -0
- package/dist/storage/local-storage.d.ts +10 -0
- package/dist/storage/local-storage.d.ts.map +1 -0
- package/dist/storage/local-storage.js +65 -0
- package/dist/storage/local-storage.js.map +1 -0
- package/dist/storage/read-upload-bytes.d.ts +3 -0
- package/dist/storage/read-upload-bytes.d.ts.map +1 -0
- package/dist/storage/read-upload-bytes.js +11 -0
- package/dist/storage/read-upload-bytes.js.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-query.js","sourceRoot":"","sources":["../../src/persistence/image-query.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,EAAE,QAAQ,EAAE,eAAe,EAAE,QAAQ,EAAE,eAAe,GAE5E,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAIxD,MAAM,UAAU,iBAAiB,CAAC,KAAqB;IACrD,MAAM,MAAM,GAA+B,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;IAC1E,IAAI,KAAK,CAAC,SAAS;QAAE,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IAC/D,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IACtD,IAAI,KAAK,CAAC,UAAU;QAAE,MAAM,CAAC,SAAS,GAAG,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC9D,IAAI,KAAK,CAAC,gBAAgB,EAAE,CAAC;QAC3B,MAAM,CAAC,gBAAgB,GAAG,KAAK,CAAC,IAAI,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;IAC5F,CAAC;IACD,MAAM,KAAK,GAAyB,EAAE,CAAC;IACvC,IAAI,KAAK,CAAC,WAAW;QAAE,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;IAChF,IAAI,KAAK,CAAC,SAAS;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,CAAC,SAAS,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC;IACnD,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9D,SAAS,CAAC,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC3D,SAAS,CAAC,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAC9D,MAAM,MAAM,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;IAC5D,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;YACd,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,KAAK,EAAE,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE;YAClE,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,GAAG,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;SACzF,CAAC,CAAC,CAAC,MAAM;QACV,KAAK,EAAE,EAAE,SAAS,EAAE,KAAK,CAAC,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,KAAK,EAAE;QAClD,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG,CAAC;KACtB,CAAC;AACJ,CAAC;AAED,SAAS,SAAS,CAChB,MAAkC,EAClC,MAAuC,EACvC,GAAuB,EACvB,GAAuB;IAEvB,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,GAAG,KAAK,SAAS;QAAE,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC;IACzD,IAAI,MAAM,CAAC,MAAM;QAAE,MAAM,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { Redis } from 'ioredis';
|
|
2
|
+
import { type DataSource } from 'typeorm';
|
|
3
|
+
import type { ListImageInput } from '../domain/schema.js';
|
|
4
|
+
import { type ImageRow } from './entities.js';
|
|
5
|
+
export declare class ImageStore {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(database: DataSource, redis: Redis, cachePrefix: string);
|
|
8
|
+
reserve(createdBy: string, key: string, hash: string, filename: string | null): Promise<{
|
|
9
|
+
row: ImageRow;
|
|
10
|
+
created: boolean;
|
|
11
|
+
}>;
|
|
12
|
+
read(id: string): Promise<ImageRow>;
|
|
13
|
+
readAsset(id: string, signal: AbortSignal): Promise<{
|
|
14
|
+
extension: "avif" | "gif" | "jpg" | "png" | "webp";
|
|
15
|
+
relativePath: string;
|
|
16
|
+
byteSize: number;
|
|
17
|
+
mediaType: "image/avif" | "image/gif" | "image/jpeg" | "image/png" | "image/webp";
|
|
18
|
+
sha256: string;
|
|
19
|
+
modifiedAt: number;
|
|
20
|
+
} | undefined>;
|
|
21
|
+
list(query: ListImageInput): Promise<{
|
|
22
|
+
items: ImageRow[];
|
|
23
|
+
hasMore: boolean;
|
|
24
|
+
nextCursor: string | null;
|
|
25
|
+
}>;
|
|
26
|
+
transition(id: string, expected: ImageRow['status'], changes: Partial<ImageRow>, signal?: AbortSignal): Promise<void>;
|
|
27
|
+
compareAndSet(id: string, expected: ImageRow['status'], changes: Partial<ImageRow>, signal?: AbortSignal): Promise<boolean>;
|
|
28
|
+
interrupted(afterId?: string): Promise<ImageRow[]>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=image-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-store.d.ts","sourceRoot":"","sources":["../../src/persistence/image-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC,OAAO,EAAgB,KAAK,UAAU,EAAmB,MAAM,SAAS,CAAC;AAGzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAe,KAAK,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG3D,qBAAa,UAAU;;IAIrB,YAAY,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,EAGlE;IACK,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;;;OAWlF;IACK,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,CAAC,CAIxC;IACD,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;mBAExC;IACK,IAAI,CAAC,KAAK,EAAE,cAAc;;;;OAK/B;IAEK,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAE1H;IAEK,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAKhI;IAEK,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CASvD;CACF"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { PublicImageCache } from '../caches/public-image-cache.js';
|
|
3
|
+
import { In, MoreThan } from 'typeorm';
|
|
4
|
+
import { encodeCursor } from '../domain/list-cursor.js';
|
|
5
|
+
import { ImageError } from '../domain/image-error.js';
|
|
6
|
+
import { ImageEntity } from './entities.js';
|
|
7
|
+
import { imageQueryOptions } from './image-query.js';
|
|
8
|
+
export class ImageStore {
|
|
9
|
+
#rows;
|
|
10
|
+
#publicImages;
|
|
11
|
+
constructor(database, redis, cachePrefix) {
|
|
12
|
+
this.#rows = database.getRepository(ImageEntity);
|
|
13
|
+
this.#publicImages = new PublicImageCache(redis, cachePrefix, (id) => this.read(id));
|
|
14
|
+
}
|
|
15
|
+
async reserve(createdBy, key, hash, filename) {
|
|
16
|
+
const id = randomUUID();
|
|
17
|
+
await this.#rows.createQueryBuilder().insert().values({
|
|
18
|
+
id, createdBy, uploadIdempotencyKey: key, uploadRequestFingerprint: hash,
|
|
19
|
+
status: 'uploading', originalFilename: filename,
|
|
20
|
+
}).orIgnore().execute();
|
|
21
|
+
const row = await this.#rows.findOneByOrFail({ createdBy, uploadIdempotencyKey: key });
|
|
22
|
+
if (row.uploadRequestFingerprint !== hash) {
|
|
23
|
+
throw new ImageError('IDEMPOTENCY_CONFLICT', '同一幂等键不能用于不同上传请求');
|
|
24
|
+
}
|
|
25
|
+
return { row, created: row.id === id };
|
|
26
|
+
}
|
|
27
|
+
async read(id) {
|
|
28
|
+
const row = await this.#rows.findOneBy({ id });
|
|
29
|
+
if (!row)
|
|
30
|
+
throw new ImageError('NOT_FOUND', '图片不存在');
|
|
31
|
+
return row;
|
|
32
|
+
}
|
|
33
|
+
readAsset(id, signal) {
|
|
34
|
+
return this.#publicImages.read(id, signal);
|
|
35
|
+
}
|
|
36
|
+
async list(query) {
|
|
37
|
+
const rows = await this.#rows.find(imageQueryOptions(query));
|
|
38
|
+
const items = rows.slice(0, query.limit);
|
|
39
|
+
const hasMore = rows.length > query.limit;
|
|
40
|
+
return { items, hasMore, nextCursor: hasMore ? encodeCursor(query, items[items.length - 1]) : null };
|
|
41
|
+
}
|
|
42
|
+
async transition(id, expected, changes, signal) {
|
|
43
|
+
if (!await this.compareAndSet(id, expected, changes, signal))
|
|
44
|
+
throw new ImageError('STATE_CONFLICT', '图片状态已改变,请重新读取');
|
|
45
|
+
}
|
|
46
|
+
async compareAndSet(id, expected, changes, signal) {
|
|
47
|
+
return this.#publicImages.change(id, async () => {
|
|
48
|
+
const result = await this.#rows.update({ id, status: expected }, changes);
|
|
49
|
+
return result.affected === 1;
|
|
50
|
+
}, signal);
|
|
51
|
+
}
|
|
52
|
+
async interrupted(afterId) {
|
|
53
|
+
return this.#rows.find({
|
|
54
|
+
where: {
|
|
55
|
+
status: In(['uploading', 'deleting', 'failed']),
|
|
56
|
+
...(afterId ? { id: MoreThan(afterId) } : {}),
|
|
57
|
+
},
|
|
58
|
+
order: { id: 'asc' },
|
|
59
|
+
take: 100,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=image-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-store.js","sourceRoot":"","sources":["../../src/persistence/image-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { ImageRow } from '../persistence/entities.js';
|
|
2
|
+
export type ImageMetadata = ReturnType<typeof imageProjection>;
|
|
3
|
+
export interface ImagePage {
|
|
4
|
+
items: ImageMetadata[];
|
|
5
|
+
hasMore: boolean;
|
|
6
|
+
nextCursor: string | null;
|
|
7
|
+
}
|
|
8
|
+
export declare function imageProjection(row: ImageRow, origin: string): {
|
|
9
|
+
id: string;
|
|
10
|
+
originalFilename: string | null;
|
|
11
|
+
status: "deleted" | "deleting" | "failed" | "ready" | "uploading";
|
|
12
|
+
url: string | null;
|
|
13
|
+
mediaType: string | null;
|
|
14
|
+
byteSize: number | null;
|
|
15
|
+
width: number | null;
|
|
16
|
+
height: number | null;
|
|
17
|
+
sha256: string | null;
|
|
18
|
+
createdBy: string;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
readyAt: string | null;
|
|
21
|
+
deletedAt: string | null;
|
|
22
|
+
failureCode: string | null;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=image-projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-projection.d.ts","sourceRoot":"","sources":["../../src/presentation/image-projection.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAE3D,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC;AAC/D,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM;IAEzD,EAAE;IACF,gBAAgB;IAChB,MAAM;IACN,GAAG;IACH,SAAS;IACT,QAAQ;IACR,KAAK;IACL,MAAM;IACN,MAAM;IACN,SAAS;IACT,SAAS;IACT,OAAO;IACP,SAAS;IACT,WAAW;EAEd"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export function imageProjection(row, origin) {
|
|
2
|
+
return {
|
|
3
|
+
id: row.id,
|
|
4
|
+
originalFilename: row.originalFilename,
|
|
5
|
+
status: row.status,
|
|
6
|
+
url: row.status === 'ready' ? new URL(`/media/images/${row.id}.${row.extension}`, origin).href : null,
|
|
7
|
+
mediaType: row.mediaType,
|
|
8
|
+
byteSize: row.byteSize,
|
|
9
|
+
width: row.width,
|
|
10
|
+
height: row.height,
|
|
11
|
+
sha256: row.sha256,
|
|
12
|
+
createdBy: row.createdBy,
|
|
13
|
+
createdAt: row.createdAt.toISOString(),
|
|
14
|
+
readyAt: row.readyAt?.toISOString() ?? null,
|
|
15
|
+
deletedAt: row.deletedAt?.toISOString() ?? null,
|
|
16
|
+
failureCode: row.failureCode,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=image-projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-projection.js","sourceRoot":"","sources":["../../src/presentation/image-projection.ts"],"names":[],"mappings":"AASA,MAAM,UAAU,eAAe,CAAC,GAAa,EAAE,MAAc;IAC3D,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,gBAAgB,EAAE,GAAG,CAAC,gBAAgB;QACtC,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,iBAAiB,GAAG,CAAC,EAAE,IAAI,GAAG,CAAC,SAAS,EAAE,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;QACrG,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,SAAS,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE;QACtC,OAAO,EAAE,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,IAAI;QAC3C,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,IAAI,IAAI;QAC/C,WAAW,EAAE,GAAG,CAAC,WAAW;KAC7B,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ImageStore } from '../persistence/image-store.js';
|
|
2
|
+
import type { LocalImageStorage } from '../storage/local-storage.js';
|
|
3
|
+
/** Runs only during single-instance startup, before either catalog is published. */
|
|
4
|
+
export declare function recoverImages(store: ImageStore, storage: LocalImageStorage): Promise<void>;
|
|
5
|
+
//# sourceMappingURL=recover-images.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recover-images.d.ts","sourceRoot":"","sources":["../../src/runtime/recover-images.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAErE,oFAAoF;AACpF,wBAAsB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBhG"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** Runs only during single-instance startup, before either catalog is published. */
|
|
2
|
+
export async function recoverImages(store, storage) {
|
|
3
|
+
let afterId;
|
|
4
|
+
for (;;) {
|
|
5
|
+
const rows = await store.interrupted(afterId);
|
|
6
|
+
if (!rows.length)
|
|
7
|
+
return;
|
|
8
|
+
for (const row of rows) {
|
|
9
|
+
if (row.relativePath)
|
|
10
|
+
await storage.remove(row.relativePath);
|
|
11
|
+
if (row.status === 'deleting') {
|
|
12
|
+
await store.transition(row.id, 'deleting', { status: 'deleted', deletedAt: new Date() });
|
|
13
|
+
}
|
|
14
|
+
if (row.status === 'uploading') {
|
|
15
|
+
await store.transition(row.id, 'uploading', { status: 'failed', failureCode: 'UPLOAD_INTERRUPTED' });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
afterId = rows[rows.length - 1].id;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=recover-images.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recover-images.js","sourceRoot":"","sources":["../../src/runtime/recover-images.ts"],"names":[],"mappings":"AAGA,oFAAoF;AACpF,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAiB,EAAE,OAA0B;IAC/E,IAAI,OAA2B,CAAC;IAChC,SAAS,CAAC;QACR,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO;QACzB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,IAAI,GAAG,CAAC,YAAY;gBAAE,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;YAC7D,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;gBAC9B,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;YAC3F,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;gBAC/B,MAAM,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAC,CAAC;YACvG,CAAC;QACH,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC,EAAE,CAAC;IACtC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application.service.d.ts","sourceRoot":"","sources":["../../src/services/application.service.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { fileURLToPath } from 'node:url';
|
|
2
|
+
import { defineService } from '@hile/core';
|
|
3
|
+
import { Application } from '@hile/micro';
|
|
4
|
+
import { parseAdvertiseHost, parseRegistryBootstrap } from '@zlooks.cn/registry-config';
|
|
5
|
+
import { detect } from 'detect-port';
|
|
6
|
+
import { IMAGES_NAMESPACE } from '../identity.js';
|
|
7
|
+
export default defineService('zlooks.images.application', async (shutdown) => {
|
|
8
|
+
const registry = parseRegistryBootstrap({
|
|
9
|
+
REGISTRY_HOST: process.env.REGISTRY_HOST,
|
|
10
|
+
REGISTRY_PORT: process.env.REGISTRY_PORT,
|
|
11
|
+
});
|
|
12
|
+
const advertiseHost = parseAdvertiseHost(process.env.HILE_ADVERTISE_HOST);
|
|
13
|
+
const application = new Application({
|
|
14
|
+
namespace: IMAGES_NAMESPACE,
|
|
15
|
+
registry,
|
|
16
|
+
...(advertiseHost ? { advertiseHost } : {}),
|
|
17
|
+
});
|
|
18
|
+
await application.load(fileURLToPath(new URL('../messages', import.meta.url)));
|
|
19
|
+
shutdown(await application.listen(await detect()));
|
|
20
|
+
return application;
|
|
21
|
+
});
|
|
22
|
+
//# sourceMappingURL=application.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"application.service.js","sourceRoot":"","sources":["../../src/services/application.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACxF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,eAAe,aAAa,CAAC,2BAA2B,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAC3E,MAAM,QAAQ,GAAG,sBAAsB,CAAC;QACtC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;QACxC,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa;KACzC,CAAC,CAAC;IACH,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;IAC1E,MAAM,WAAW,GAAG,IAAI,WAAW,CAAC;QAClC,SAAS,EAAE,gBAAgB;QAC3B,QAAQ;QACR,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAC,CAAC;IACH,MAAM,WAAW,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,aAAa,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC/E,QAAQ,CAAC,MAAM,WAAW,CAAC,MAAM,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC;IACnD,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
declare const _default: import("@hile/core").ServiceRegisterProps<import("@zlooks.cn/registry-config").RegistryConfigSubscription<Readonly<{
|
|
2
|
+
postgres: Readonly<{
|
|
3
|
+
host: string;
|
|
4
|
+
port: number;
|
|
5
|
+
username: string;
|
|
6
|
+
password: string;
|
|
7
|
+
database: string;
|
|
8
|
+
ssl: boolean;
|
|
9
|
+
poolSize: number;
|
|
10
|
+
}>;
|
|
11
|
+
redis: Readonly<{
|
|
12
|
+
host: string;
|
|
13
|
+
port: number;
|
|
14
|
+
username?: string | undefined;
|
|
15
|
+
password?: string | undefined;
|
|
16
|
+
database: number;
|
|
17
|
+
keyPrefix: string;
|
|
18
|
+
tls: boolean;
|
|
19
|
+
}>;
|
|
20
|
+
publicHost: Readonly<{
|
|
21
|
+
origin: string;
|
|
22
|
+
}>;
|
|
23
|
+
}>>>;
|
|
24
|
+
export default _default;
|
|
25
|
+
//# sourceMappingURL=config.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.service.d.ts","sourceRoot":"","sources":["../../src/services/config.service.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineService, loadService } from '@hile/core';
|
|
2
|
+
import { parsePostgresConfig, parseRedisConfig } from '@zlooks.cn/infrastructure';
|
|
3
|
+
import { parsePublicHostConfig, PUBLIC_HOST_CONFIG_TOPIC_KEY } from '@zlooks.cn/public-host-contract';
|
|
4
|
+
import { registryConfigTopic, subscribeRegistryConfig } from '@zlooks.cn/registry-config';
|
|
5
|
+
import applicationService from './application.service.js';
|
|
6
|
+
export default defineService('zlooks.images.config', async (shutdown) => {
|
|
7
|
+
const application = await loadService(applicationService);
|
|
8
|
+
const subscriber = await subscribeRegistryConfig(application, {
|
|
9
|
+
sources: {
|
|
10
|
+
redis: { topic: registryConfigTopic('redis'), parse: parseRedisConfig },
|
|
11
|
+
postgres: { topic: registryConfigTopic('postgres'), parse: parsePostgresConfig },
|
|
12
|
+
publicHost: { topic: registryConfigTopic(PUBLIC_HOST_CONFIG_TOPIC_KEY), parse: parsePublicHostConfig },
|
|
13
|
+
},
|
|
14
|
+
compose: (sources) => Object.freeze({ postgres: sources.postgres, redis: sources.redis, publicHost: sources.publicHost }),
|
|
15
|
+
});
|
|
16
|
+
shutdown(() => subscriber.close());
|
|
17
|
+
return subscriber;
|
|
18
|
+
});
|
|
19
|
+
//# sourceMappingURL=config.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.service.js","sourceRoot":"","sources":["../../src/services/config.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClF,OAAO,EAAE,qBAAqB,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AACtG,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAC1F,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAE1D,eAAe,aAAa,CAAC,sBAAsB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IACtE,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,MAAM,uBAAuB,CAAC,WAAW,EAAE;QAC5D,OAAO,EAAE;YACP,KAAK,EAAE,EAAE,KAAK,EAAE,mBAAmB,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,gBAAgB,EAAE;YACvE,QAAQ,EAAE,EAAE,KAAK,EAAE,mBAAmB,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE;YAChF,UAAU,EAAE,EAAE,KAAK,EAAE,mBAAmB,CAAC,4BAA4B,CAAC,EAAE,KAAK,EAAE,qBAAqB,EAAE;SACvG;QACD,OAAO,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC;KAC1H,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;IACnC,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.service.d.ts","sourceRoot":"","sources":["../../src/services/database.service.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { defineService, loadService } from '@hile/core';
|
|
2
|
+
import { createDataSource } from '@hile/typeorm';
|
|
3
|
+
import { ImageEntity } from '../persistence/entities.js';
|
|
4
|
+
import configService from './config.service.js';
|
|
5
|
+
export default defineService('zlooks.images.database', async (shutdown) => {
|
|
6
|
+
const config = (await loadService(configService)).snapshot().postgres;
|
|
7
|
+
const database = await createDataSource({
|
|
8
|
+
type: 'postgres',
|
|
9
|
+
host: config.host,
|
|
10
|
+
port: config.port,
|
|
11
|
+
username: config.username,
|
|
12
|
+
password: config.password,
|
|
13
|
+
database: config.database,
|
|
14
|
+
ssl: config.ssl,
|
|
15
|
+
poolSize: config.poolSize,
|
|
16
|
+
synchronize: true,
|
|
17
|
+
migrationsRun: false,
|
|
18
|
+
entities: [ImageEntity],
|
|
19
|
+
});
|
|
20
|
+
shutdown(() => database.destroy());
|
|
21
|
+
return database;
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=database.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.service.js","sourceRoot":"","sources":["../../src/services/database.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAEhD,eAAe,aAAa,CAAC,wBAAwB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IACxE,MAAM,MAAM,GAAG,CAAC,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACtE,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC;QACtC,IAAI,EAAE,UAAU;QAChB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,GAAG,EAAE,MAAM,CAAC,GAAG;QACf,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,IAAI;QACjB,aAAa,EAAE,KAAK;QACpB,QAAQ,EAAE,CAAC,WAAW,CAAC;KACxB,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACnC,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ImageStore } from '../persistence/image-store.js';
|
|
2
|
+
import { LocalImageStorage } from '../storage/local-storage.js';
|
|
3
|
+
declare const _default: import("@hile/core").ServiceRegisterProps<{
|
|
4
|
+
store: ImageStore;
|
|
5
|
+
storage: LocalImageStorage;
|
|
6
|
+
origin: () => any;
|
|
7
|
+
}>;
|
|
8
|
+
export default _default;
|
|
9
|
+
//# sourceMappingURL=images-runtime.service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images-runtime.service.d.ts","sourceRoot":"","sources":["../../src/services/images-runtime.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAE3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { defineService, loadService } from '@hile/core';
|
|
2
|
+
import { ImageStore } from '../persistence/image-store.js';
|
|
3
|
+
import { recoverImages } from '../runtime/recover-images.js';
|
|
4
|
+
import { LocalImageStorage } from '../storage/local-storage.js';
|
|
5
|
+
import configService from './config.service.js';
|
|
6
|
+
import redisService from './redis.service.js';
|
|
7
|
+
import databaseService from './database.service.js';
|
|
8
|
+
export default defineService('zlooks.images.runtime', async () => {
|
|
9
|
+
const [database, configs, redis] = await Promise.all([loadService(databaseService), loadService(configService), loadService(redisService)]);
|
|
10
|
+
const store = new ImageStore(database, redis, `${configs.snapshot().redis.keyPrefix}images:public:v1:`);
|
|
11
|
+
const storage = new LocalImageStorage();
|
|
12
|
+
await storage.initialize();
|
|
13
|
+
await recoverImages(store, storage);
|
|
14
|
+
return { store, storage, origin: () => configs.snapshot().publicHost.origin };
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=images-runtime.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images-runtime.service.js","sourceRoot":"","sources":["../../src/services/images-runtime.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,YAAY,MAAM,oBAAoB,CAAC;AAC9C,OAAO,eAAe,MAAM,uBAAuB,CAAC;AAEpD,eAAe,aAAa,CAAC,uBAAuB,EAAE,KAAK,IAAI,EAAE;IAC/D,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,eAAe,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;IAC5I,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC,SAAS,mBAAmB,CAAC,CAAC;IACxG,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;IACxC,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC;IAC3B,MAAM,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACpC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;AAChF,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.boot.d.ts","sourceRoot":"","sources":["../../src/services/images.boot.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineService, loadService } from '@hile/core';
|
|
2
|
+
import publicAssetsService from './public-assets.service.js';
|
|
3
|
+
import mcpProviderService from './mcp-provider.service.js';
|
|
4
|
+
export default defineService('zlooks.images.boot', async () => {
|
|
5
|
+
await loadService(publicAssetsService);
|
|
6
|
+
await loadService(mcpProviderService);
|
|
7
|
+
});
|
|
8
|
+
//# sourceMappingURL=images.boot.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"images.boot.js","sourceRoot":"","sources":["../../src/services/images.boot.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,mBAAmB,MAAM,4BAA4B,CAAC;AAC7D,OAAO,kBAAkB,MAAM,2BAA2B,CAAC;AAE3D,eAAe,aAAa,CAAC,oBAAoB,EAAE,KAAK,IAAI,EAAE;IAC5D,MAAM,WAAW,CAAC,mBAAmB,CAAC,CAAC;IACvC,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.service.d.ts","sourceRoot":"","sources":["../../src/services/logger.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { defineService } from '@hile/core';
|
|
2
|
+
import { createLogger } from '@hile/logger';
|
|
3
|
+
export default defineService('zlooks.images.logger', async (shutdown) => {
|
|
4
|
+
const { logger, teardown } = createLogger({ level: 'info', pretty: false });
|
|
5
|
+
shutdown(teardown);
|
|
6
|
+
return logger;
|
|
7
|
+
});
|
|
8
|
+
//# sourceMappingURL=logger.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.service.js","sourceRoot":"","sources":["../../src/services/logger.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAe,MAAM,cAAc,CAAC;AAEzD,eAAe,aAAa,CAAC,sBAAsB,EAAE,KAAK,EAAE,QAAQ,EAAmB,EAAE;IACvF,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5E,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-provider.service.d.ts","sourceRoot":"","sources":["../../src/services/mcp-provider.service.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineService, loadService } from '@hile/core';
|
|
2
|
+
import { attachMcpProvider } from '@hile/mcp/micro';
|
|
3
|
+
import { createImagesProvider } from '../mcp/provider.js';
|
|
4
|
+
import applicationService from './application.service.js';
|
|
5
|
+
import imagesRuntimeService from './images-runtime.service.js';
|
|
6
|
+
export default defineService('zlooks.images.mcp-provider', async (shutdown) => {
|
|
7
|
+
await loadService(imagesRuntimeService);
|
|
8
|
+
const application = await loadService(applicationService);
|
|
9
|
+
const attachment = await attachMcpProvider(application, createImagesProvider(), {
|
|
10
|
+
invocationSecurity: { mode: 'trusted-internal' },
|
|
11
|
+
});
|
|
12
|
+
shutdown(() => attachment.close());
|
|
13
|
+
return attachment;
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=mcp-provider.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-provider.service.js","sourceRoot":"","sources":["../../src/services/mcp-provider.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,oBAAoB,MAAM,6BAA6B,CAAC;AAE/D,eAAe,aAAa,CAAC,4BAA4B,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAC5E,MAAM,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACxC,MAAM,WAAW,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,WAAW,EAAE,oBAAoB,EAAE,EAAE;QAC9E,kBAAkB,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;KACjD,CAAC,CAAC;IACH,QAAQ,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;IACnC,OAAO,UAAU,CAAC;AACpB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-assets.service.d.ts","sourceRoot":"","sources":["../../src/services/public-assets.service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { defineService, loadService } from '@hile/core';
|
|
2
|
+
import { PublicAssetPublisher } from '@zlooks.cn/public-asset/publisher';
|
|
3
|
+
import { imageAssetProvider } from '../assets/provider.js';
|
|
4
|
+
import applicationService from './application.service.js';
|
|
5
|
+
import imagesRuntimeService from './images-runtime.service.js';
|
|
6
|
+
import loggerService from './logger.service.js';
|
|
7
|
+
export default defineService('zlooks.images.public-assets', async (shutdown) => {
|
|
8
|
+
await loadService(imagesRuntimeService);
|
|
9
|
+
const [application, logger] = await Promise.all([loadService(applicationService), loadService(loggerService)]);
|
|
10
|
+
const publisher = new PublicAssetPublisher(application, imageAssetProvider, (error) => logger.error({ err: error, event: 'images.publication.failed' }, 'Image read publication failed'));
|
|
11
|
+
shutdown(() => publisher.close());
|
|
12
|
+
await publisher.start();
|
|
13
|
+
return publisher;
|
|
14
|
+
});
|
|
15
|
+
//# sourceMappingURL=public-assets.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"public-assets.service.js","sourceRoot":"","sources":["../../src/services/public-assets.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,kBAAkB,MAAM,0BAA0B,CAAC;AAC1D,OAAO,oBAAoB,MAAM,6BAA6B,CAAC;AAC/D,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAEhD,eAAe,aAAa,CAAC,6BAA6B,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IAC7E,MAAM,WAAW,CAAC,oBAAoB,CAAC,CAAC;IACxC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,kBAAkB,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IAC/G,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC,WAAW,EAAE,kBAAkB,EACxE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,2BAA2B,EAAE,EAAE,+BAA+B,CAAC,CAAC,CAAC;IAChH,QAAQ,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC;IAClC,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;IACxB,OAAO,SAAS,CAAC;AACnB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.service.d.ts","sourceRoot":"","sources":["../../src/services/redis.service.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { once } from 'node:events';
|
|
2
|
+
import { defineService, loadService } from '@hile/core';
|
|
3
|
+
import { createRedis } from '@hile/ioredis';
|
|
4
|
+
import configService from './config.service.js';
|
|
5
|
+
import loggerService from './logger.service.js';
|
|
6
|
+
export default defineService('zlooks.images.redis', async (shutdown) => {
|
|
7
|
+
const [configs, logger] = await Promise.all([loadService(configService), loadService(loggerService)]);
|
|
8
|
+
const config = configs.snapshot().redis;
|
|
9
|
+
let ready = false;
|
|
10
|
+
const redis = await createRedis({
|
|
11
|
+
host: config.host, port: config.port, db: config.database,
|
|
12
|
+
...(config.username ? { username: config.username } : {}),
|
|
13
|
+
...(config.password ? { password: config.password } : {}),
|
|
14
|
+
...(config.tls ? { tls: {} } : {}),
|
|
15
|
+
connectTimeout: 3_000, commandTimeout: 3_000, maxRetriesPerRequest: 1, enableOfflineQueue: false,
|
|
16
|
+
// createRedis cannot expose a failed initial client for cleanup; stop initial retries.
|
|
17
|
+
retryStrategy: (attempt) => ready ? Math.min(attempt * 100, 1_000) : null,
|
|
18
|
+
});
|
|
19
|
+
const onError = () => logger.warn('图片元数据缓存 Redis 连接异常');
|
|
20
|
+
redis.on('error', onError);
|
|
21
|
+
shutdown(() => { redis.disconnect(); redis.off('error', onError); });
|
|
22
|
+
try {
|
|
23
|
+
// createRedis resolves at TCP connect; connect alone does not verify authentication/readiness.
|
|
24
|
+
if (redis.status !== 'ready')
|
|
25
|
+
await once(redis, 'ready', { signal: AbortSignal.timeout(3_000) });
|
|
26
|
+
ready = true;
|
|
27
|
+
return redis;
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
redis.disconnect();
|
|
31
|
+
redis.off('error', onError);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
//# sourceMappingURL=redis.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"redis.service.js","sourceRoot":"","sources":["../../src/services/redis.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAChD,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAEhD,eAAe,aAAa,CAAC,qBAAqB,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;IACrE,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,aAAa,CAAC,EAAE,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;IACtG,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,CAAC;IACxC,IAAI,KAAK,GAAG,KAAK,CAAC;IAClB,MAAM,KAAK,GAAG,MAAM,WAAW,CAAC;QAC9B,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,QAAQ;QACzD,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzD,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAClC,cAAc,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC,EAAE,kBAAkB,EAAE,KAAK;QAChG,uFAAuF;QACvF,aAAa,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,GAAG,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI;KAC1E,CAAC,CAAC;IACH,MAAM,OAAO,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACxD,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC;QACH,+FAA+F;QAC/F,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO;YAAE,MAAM,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjG,KAAK,GAAG,IAAI,CAAC;QACb,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QAAC,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAAC,MAAM,KAAK,CAAC;IAAC,CAAC;AACnF,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-path.d.ts","sourceRoot":"","sources":["../../src/storage/image-path.ts"],"names":[],"mappings":"AAQA,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,GAAG,MAAM,CAIlF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { ImageError } from '../domain/image-error.js';
|
|
3
|
+
const relativePattern = /^\d{4}\/\d{2}\/\d{2}\/[a-f0-9-]{36}\.(?:jpg|png|webp|gif|avif)$/;
|
|
4
|
+
const calendar = new Intl.DateTimeFormat('en-CA', {
|
|
5
|
+
timeZone: 'Asia/Shanghai', year: 'numeric', month: '2-digit', day: '2-digit',
|
|
6
|
+
});
|
|
7
|
+
export function validateImagePath(relative) {
|
|
8
|
+
if (!relativePattern.test(relative))
|
|
9
|
+
throw new ImageError('INVALID_PATH', '图片路径无效');
|
|
10
|
+
return relative;
|
|
11
|
+
}
|
|
12
|
+
export function imageRelativePath(id, extension, now) {
|
|
13
|
+
z.uuid().parse(id);
|
|
14
|
+
const parts = Object.fromEntries(calendar.formatToParts(now).map((part) => [part.type, part.value]));
|
|
15
|
+
return validateImagePath(`${parts.year}/${parts.month}/${parts.day}/${id}.${extension}`);
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=image-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-path.js","sourceRoot":"","sources":["../../src/storage/image-path.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEtD,MAAM,eAAe,GAAG,iEAAiE,CAAC;AAC1F,MAAM,QAAQ,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;IAChD,QAAQ,EAAE,eAAe,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,SAAS;CAC7E,CAAC,CAAC;AAEH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,UAAU,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACpF,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,EAAU,EAAE,SAAiB,EAAE,GAAS;IACxE,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACnB,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACrG,OAAO,iBAAiB,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,GAAG,IAAI,EAAE,IAAI,SAAS,EAAE,CAAC,CAAC;AAC3F,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare function inspectImage(bytes: Buffer): Promise<{
|
|
2
|
+
mediaType: "image/avif" | "image/gif" | "image/jpeg" | "image/png" | "image/webp";
|
|
3
|
+
extension: "avif" | "gif" | "jpg" | "png" | "webp";
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
byteSize: number;
|
|
7
|
+
sha256: string;
|
|
8
|
+
}>;
|
|
9
|
+
//# sourceMappingURL=inspect-image.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inspect-image.d.ts","sourceRoot":"","sources":["../../src/storage/inspect-image.ts"],"names":[],"mappings":"AAUA,wBAAsB,YAAY,CAAC,KAAK,EAAE,MAAM;;;;;;;GAuB/C"}
|