@open-mercato/core 0.4.5-develop-995ce486fa → 0.4.5-develop-8a56591995
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/generated/entities/progress_job/index.js +57 -0
- package/dist/generated/entities/progress_job/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +4 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/progress/__integration__/TC-PROG-001.spec.js +51 -0
- package/dist/modules/progress/__integration__/TC-PROG-001.spec.js.map +7 -0
- package/dist/modules/progress/acl.js +33 -0
- package/dist/modules/progress/acl.js.map +7 -0
- package/dist/modules/progress/api/active/route.js +57 -0
- package/dist/modules/progress/api/active/route.js.map +7 -0
- package/dist/modules/progress/api/jobs/[id]/route.js +126 -0
- package/dist/modules/progress/api/jobs/[id]/route.js.map +7 -0
- package/dist/modules/progress/api/jobs/route.js +156 -0
- package/dist/modules/progress/api/jobs/route.js.map +7 -0
- package/dist/modules/progress/api/openapi.js +27 -0
- package/dist/modules/progress/api/openapi.js.map +7 -0
- package/dist/modules/progress/data/entities.js +113 -0
- package/dist/modules/progress/data/entities.js.map +7 -0
- package/dist/modules/progress/data/validators.js +48 -0
- package/dist/modules/progress/data/validators.js.map +7 -0
- package/dist/modules/progress/di.js +16 -0
- package/dist/modules/progress/di.js.map +7 -0
- package/dist/modules/progress/events.js +22 -0
- package/dist/modules/progress/events.js.map +7 -0
- package/dist/modules/progress/index.js +13 -0
- package/dist/modules/progress/index.js.map +7 -0
- package/dist/modules/progress/lib/events.js +14 -0
- package/dist/modules/progress/lib/events.js.map +7 -0
- package/dist/modules/progress/lib/progressService.js +21 -0
- package/dist/modules/progress/lib/progressService.js.map +7 -0
- package/dist/modules/progress/lib/progressServiceImpl.js +215 -0
- package/dist/modules/progress/lib/progressServiceImpl.js.map +7 -0
- package/dist/modules/progress/migrations/Migration20260220214819.js +16 -0
- package/dist/modules/progress/migrations/Migration20260220214819.js.map +7 -0
- package/dist/modules/progress/setup.js +12 -0
- package/dist/modules/progress/setup.js.map +7 -0
- package/generated/entities/progress_job/index.ts +27 -0
- package/generated/entities.ids.generated.ts +4 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +2 -2
- package/src/modules/progress/__integration__/TC-PROG-001.spec.ts +67 -0
- package/src/modules/progress/__tests__/progressService.test.ts +377 -0
- package/src/modules/progress/acl.ts +29 -0
- package/src/modules/progress/api/active/route.ts +61 -0
- package/src/modules/progress/api/jobs/[id]/route.ts +136 -0
- package/src/modules/progress/api/jobs/route.ts +192 -0
- package/src/modules/progress/api/openapi.ts +28 -0
- package/src/modules/progress/data/entities.ts +94 -0
- package/src/modules/progress/data/validators.ts +51 -0
- package/src/modules/progress/di.ts +15 -0
- package/src/modules/progress/events.ts +21 -0
- package/src/modules/progress/i18n/de.json +20 -0
- package/src/modules/progress/i18n/en.json +20 -0
- package/src/modules/progress/i18n/es.json +20 -0
- package/src/modules/progress/i18n/pl.json +20 -0
- package/src/modules/progress/index.ts +11 -0
- package/src/modules/progress/lib/events.ts +60 -0
- package/src/modules/progress/lib/progressService.ts +47 -0
- package/src/modules/progress/lib/progressServiceImpl.ts +261 -0
- package/src/modules/progress/migrations/.snapshot-open-mercato.json +316 -0
- package/src/modules/progress/migrations/Migration20260220214819.ts +15 -0
- package/src/modules/progress/setup.ts +10 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
4
|
+
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
5
|
+
import { escapeLikePattern } from "@open-mercato/shared/lib/db/escapeLikePattern";
|
|
6
|
+
import { ProgressJob } from "../../data/entities.js";
|
|
7
|
+
import { createProgressJobSchema, listProgressJobsSchema } from "../../data/validators.js";
|
|
8
|
+
import {
|
|
9
|
+
createProgressCrudOpenApi,
|
|
10
|
+
createPagedListResponseSchema
|
|
11
|
+
} from "../openapi.js";
|
|
12
|
+
const routeMetadata = {
|
|
13
|
+
GET: { requireAuth: true, requireFeatures: ["progress.view"] },
|
|
14
|
+
POST: { requireAuth: true, requireFeatures: ["progress.create"] }
|
|
15
|
+
};
|
|
16
|
+
const metadata = routeMetadata;
|
|
17
|
+
const listQuerySchema = listProgressJobsSchema;
|
|
18
|
+
const toRow = (job) => ({
|
|
19
|
+
id: String(job.id),
|
|
20
|
+
jobType: String(job.jobType),
|
|
21
|
+
name: String(job.name),
|
|
22
|
+
description: job.description ?? null,
|
|
23
|
+
status: job.status,
|
|
24
|
+
progressPercent: job.progressPercent,
|
|
25
|
+
processedCount: job.processedCount,
|
|
26
|
+
totalCount: job.totalCount ?? null,
|
|
27
|
+
etaSeconds: job.etaSeconds ?? null,
|
|
28
|
+
cancellable: !!job.cancellable,
|
|
29
|
+
startedAt: job.startedAt ? job.startedAt.toISOString() : null,
|
|
30
|
+
finishedAt: job.finishedAt ? job.finishedAt.toISOString() : null,
|
|
31
|
+
errorMessage: job.errorMessage ?? null,
|
|
32
|
+
createdAt: job.createdAt ? job.createdAt.toISOString() : null,
|
|
33
|
+
tenantId: String(job.tenantId),
|
|
34
|
+
organizationId: job.organizationId ? String(job.organizationId) : null
|
|
35
|
+
});
|
|
36
|
+
async function GET(req) {
|
|
37
|
+
const auth = await getAuthFromRequest(req);
|
|
38
|
+
if (!auth || !auth.tenantId) {
|
|
39
|
+
return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 401 });
|
|
40
|
+
}
|
|
41
|
+
const url = new URL(req.url);
|
|
42
|
+
const parsed = listQuerySchema.safeParse({
|
|
43
|
+
status: url.searchParams.get("status") ?? void 0,
|
|
44
|
+
jobType: url.searchParams.get("jobType") ?? void 0,
|
|
45
|
+
parentJobId: url.searchParams.get("parentJobId") ?? void 0,
|
|
46
|
+
includeCompleted: url.searchParams.get("includeCompleted") ?? void 0,
|
|
47
|
+
completedSince: url.searchParams.get("completedSince") ?? void 0,
|
|
48
|
+
page: url.searchParams.get("page") ?? void 0,
|
|
49
|
+
pageSize: url.searchParams.get("pageSize") ?? void 0,
|
|
50
|
+
search: url.searchParams.get("search") ?? void 0,
|
|
51
|
+
sortField: url.searchParams.get("sortField") ?? void 0,
|
|
52
|
+
sortDir: url.searchParams.get("sortDir") ?? void 0
|
|
53
|
+
});
|
|
54
|
+
if (!parsed.success) {
|
|
55
|
+
return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 400 });
|
|
56
|
+
}
|
|
57
|
+
const container = await createRequestContainer();
|
|
58
|
+
const em = container.resolve("em");
|
|
59
|
+
const { status, jobType, parentJobId, includeCompleted, completedSince, page, pageSize, search, sortField, sortDir } = parsed.data;
|
|
60
|
+
const filter = {
|
|
61
|
+
tenantId: auth.tenantId
|
|
62
|
+
};
|
|
63
|
+
if (auth.orgId) {
|
|
64
|
+
filter.organizationId = auth.orgId;
|
|
65
|
+
}
|
|
66
|
+
if (status) {
|
|
67
|
+
const statusValues = status.split(",");
|
|
68
|
+
filter.status = statusValues.length > 1 ? { $in: statusValues } : status;
|
|
69
|
+
} else if (includeCompleted !== "true") {
|
|
70
|
+
filter.status = { $in: ["pending", "running"] };
|
|
71
|
+
}
|
|
72
|
+
if (jobType) filter.jobType = jobType;
|
|
73
|
+
if (parentJobId) filter.parentJobId = parentJobId;
|
|
74
|
+
if (completedSince) filter.finishedAt = { $gte: new Date(completedSince) };
|
|
75
|
+
if (search) {
|
|
76
|
+
const escaped = escapeLikePattern(search);
|
|
77
|
+
filter.$or = [
|
|
78
|
+
{ name: { $ilike: `%${escaped}%` } },
|
|
79
|
+
{ jobType: { $ilike: `%${escaped}%` } }
|
|
80
|
+
];
|
|
81
|
+
}
|
|
82
|
+
const fieldMap = {
|
|
83
|
+
createdAt: "createdAt",
|
|
84
|
+
startedAt: "startedAt",
|
|
85
|
+
finishedAt: "finishedAt"
|
|
86
|
+
};
|
|
87
|
+
const orderBy = {};
|
|
88
|
+
if (sortField) {
|
|
89
|
+
const mapped = fieldMap[sortField] || "createdAt";
|
|
90
|
+
orderBy[mapped] = sortDir === "asc" ? "ASC" : "DESC";
|
|
91
|
+
} else {
|
|
92
|
+
orderBy.createdAt = "DESC";
|
|
93
|
+
}
|
|
94
|
+
const [rows, total] = await em.findAndCount(ProgressJob, filter, {
|
|
95
|
+
orderBy,
|
|
96
|
+
limit: pageSize,
|
|
97
|
+
offset: (page - 1) * pageSize
|
|
98
|
+
});
|
|
99
|
+
const items = rows.map(toRow);
|
|
100
|
+
const totalPages = Math.max(1, Math.ceil(total / pageSize));
|
|
101
|
+
return NextResponse.json({ items, total, page, pageSize, totalPages });
|
|
102
|
+
}
|
|
103
|
+
async function POST(req) {
|
|
104
|
+
const auth = await getAuthFromRequest(req);
|
|
105
|
+
if (!auth || !auth.tenantId) {
|
|
106
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
107
|
+
}
|
|
108
|
+
const body = await req.json();
|
|
109
|
+
const parsed = createProgressJobSchema.safeParse(body);
|
|
110
|
+
if (!parsed.success) {
|
|
111
|
+
return NextResponse.json({ error: "Invalid input", details: parsed.error.flatten() }, { status: 400 });
|
|
112
|
+
}
|
|
113
|
+
const container = await createRequestContainer();
|
|
114
|
+
const progressService = container.resolve("progressService");
|
|
115
|
+
const job = await progressService.createJob(parsed.data, {
|
|
116
|
+
tenantId: auth.tenantId,
|
|
117
|
+
organizationId: auth.orgId,
|
|
118
|
+
userId: auth.sub
|
|
119
|
+
});
|
|
120
|
+
return NextResponse.json({ id: job.id }, { status: 201 });
|
|
121
|
+
}
|
|
122
|
+
const jobListItemSchema = z.object({
|
|
123
|
+
id: z.string().uuid(),
|
|
124
|
+
jobType: z.string(),
|
|
125
|
+
name: z.string(),
|
|
126
|
+
description: z.string().nullable(),
|
|
127
|
+
status: z.string(),
|
|
128
|
+
progressPercent: z.number(),
|
|
129
|
+
processedCount: z.number(),
|
|
130
|
+
totalCount: z.number().nullable(),
|
|
131
|
+
etaSeconds: z.number().nullable(),
|
|
132
|
+
cancellable: z.boolean(),
|
|
133
|
+
startedAt: z.string().nullable(),
|
|
134
|
+
finishedAt: z.string().nullable(),
|
|
135
|
+
errorMessage: z.string().nullable(),
|
|
136
|
+
createdAt: z.string().nullable(),
|
|
137
|
+
tenantId: z.string().uuid(),
|
|
138
|
+
organizationId: z.string().uuid().nullable()
|
|
139
|
+
});
|
|
140
|
+
const openApi = createProgressCrudOpenApi({
|
|
141
|
+
resourceName: "ProgressJob",
|
|
142
|
+
pluralName: "ProgressJobs",
|
|
143
|
+
querySchema: listQuerySchema,
|
|
144
|
+
listResponseSchema: createPagedListResponseSchema(jobListItemSchema),
|
|
145
|
+
create: {
|
|
146
|
+
schema: createProgressJobSchema,
|
|
147
|
+
description: "Creates a new progress job for tracking a long-running operation."
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
export {
|
|
151
|
+
GET,
|
|
152
|
+
POST,
|
|
153
|
+
metadata,
|
|
154
|
+
openApi
|
|
155
|
+
};
|
|
156
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/progress/api/jobs/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { FilterQuery } from '@mikro-orm/core'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport { ProgressJob } from '../../data/entities'\nimport { createProgressJobSchema, listProgressJobsSchema } from '../../data/validators'\nimport {\n createProgressCrudOpenApi,\n createPagedListResponseSchema,\n} from '../openapi'\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['progress.view'] },\n POST: { requireAuth: true, requireFeatures: ['progress.create'] },\n}\n\nexport const metadata = routeMetadata\n\nconst listQuerySchema = listProgressJobsSchema\n\ntype JobRow = {\n id: string\n jobType: string\n name: string\n description: string | null\n status: string\n progressPercent: number\n processedCount: number\n totalCount: number | null\n etaSeconds: number | null\n cancellable: boolean\n startedAt: string | null\n finishedAt: string | null\n errorMessage: string | null\n createdAt: string | null\n tenantId: string\n organizationId: string | null\n}\n\nconst toRow = (job: ProgressJob): JobRow => ({\n id: String(job.id),\n jobType: String(job.jobType),\n name: String(job.name),\n description: job.description ?? null,\n status: job.status,\n progressPercent: job.progressPercent,\n processedCount: job.processedCount,\n totalCount: job.totalCount ?? null,\n etaSeconds: job.etaSeconds ?? null,\n cancellable: !!job.cancellable,\n startedAt: job.startedAt ? job.startedAt.toISOString() : null,\n finishedAt: job.finishedAt ? job.finishedAt.toISOString() : null,\n errorMessage: job.errorMessage ?? null,\n createdAt: job.createdAt ? job.createdAt.toISOString() : null,\n tenantId: String(job.tenantId),\n organizationId: job.organizationId ? String(job.organizationId) : null,\n})\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = listQuerySchema.safeParse({\n status: url.searchParams.get('status') ?? undefined,\n jobType: url.searchParams.get('jobType') ?? undefined,\n parentJobId: url.searchParams.get('parentJobId') ?? undefined,\n includeCompleted: url.searchParams.get('includeCompleted') ?? undefined,\n completedSince: url.searchParams.get('completedSince') ?? undefined,\n page: url.searchParams.get('page') ?? undefined,\n pageSize: url.searchParams.get('pageSize') ?? undefined,\n search: url.searchParams.get('search') ?? undefined,\n sortField: url.searchParams.get('sortField') ?? undefined,\n sortDir: url.searchParams.get('sortDir') ?? undefined,\n })\n if (!parsed.success) {\n return NextResponse.json({ items: [], total: 0, page: 1, pageSize: 20, totalPages: 1 }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const { status, jobType, parentJobId, includeCompleted, completedSince, page, pageSize, search, sortField, sortDir } = parsed.data\n const filter: FilterQuery<ProgressJob> = {\n tenantId: auth.tenantId,\n }\n\n if (auth.orgId) {\n filter.organizationId = auth.orgId\n }\n\n if (status) {\n const statusValues = status.split(',')\n filter.status = statusValues.length > 1 ? { $in: statusValues as never } : status as never\n } else if (includeCompleted !== 'true') {\n filter.status = { $in: ['pending', 'running'] }\n }\n\n if (jobType) filter.jobType = jobType\n if (parentJobId) filter.parentJobId = parentJobId\n if (completedSince) filter.finishedAt = { $gte: new Date(completedSince) }\n\n if (search) {\n const escaped = escapeLikePattern(search)\n filter.$or = [\n { name: { $ilike: `%${escaped}%` } },\n { jobType: { $ilike: `%${escaped}%` } },\n ]\n }\n\n const fieldMap: Record<string, string> = {\n createdAt: 'createdAt',\n startedAt: 'startedAt',\n finishedAt: 'finishedAt',\n }\n const orderBy: Record<string, 'ASC' | 'DESC'> = {}\n if (sortField) {\n const mapped = fieldMap[sortField] || 'createdAt'\n orderBy[mapped] = sortDir === 'asc' ? 'ASC' : 'DESC'\n } else {\n orderBy.createdAt = 'DESC'\n }\n\n const [rows, total] = await em.findAndCount(ProgressJob, filter, {\n orderBy,\n limit: pageSize,\n offset: (page - 1) * pageSize,\n })\n const items = rows.map(toRow)\n const totalPages = Math.max(1, Math.ceil(total / pageSize))\n\n return NextResponse.json({ items, total, page, pageSize, totalPages })\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth || !auth.tenantId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const body = await req.json()\n const parsed = createProgressJobSchema.safeParse(body)\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid input', details: parsed.error.flatten() }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const progressService = container.resolve('progressService') as import('../../lib/progressService').ProgressService\n\n const job = await progressService.createJob(parsed.data, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub,\n })\n\n return NextResponse.json({ id: job.id }, { status: 201 })\n}\n\nconst jobListItemSchema = z.object({\n id: z.string().uuid(),\n jobType: z.string(),\n name: z.string(),\n description: z.string().nullable(),\n status: z.string(),\n progressPercent: z.number(),\n processedCount: z.number(),\n totalCount: z.number().nullable(),\n etaSeconds: z.number().nullable(),\n cancellable: z.boolean(),\n startedAt: z.string().nullable(),\n finishedAt: z.string().nullable(),\n errorMessage: z.string().nullable(),\n createdAt: z.string().nullable(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid().nullable(),\n})\n\nexport const openApi = createProgressCrudOpenApi({\n resourceName: 'ProgressJob',\n pluralName: 'ProgressJobs',\n querySchema: listQuerySchema,\n listResponseSchema: createPagedListResponseSchema(jobListItemSchema),\n create: {\n schema: createProgressJobSchema,\n description: 'Creates a new progress job for tracking a long-running operation.',\n },\n})\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createCrudOpenApiFactory,
|
|
3
|
+
createPagedListResponseSchema as createSharedPagedListResponseSchema,
|
|
4
|
+
defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,
|
|
5
|
+
defaultOkResponseSchema as sharedDefaultOkResponseSchema
|
|
6
|
+
} from "@open-mercato/shared/lib/openapi/crud";
|
|
7
|
+
const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema;
|
|
8
|
+
const defaultOkResponseSchema = sharedDefaultOkResponseSchema;
|
|
9
|
+
function createPagedListResponseSchema(itemSchema) {
|
|
10
|
+
return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true });
|
|
11
|
+
}
|
|
12
|
+
const buildProgressCrudOpenApi = createCrudOpenApiFactory({
|
|
13
|
+
defaultTag: "Progress",
|
|
14
|
+
defaultCreateResponseSchema,
|
|
15
|
+
defaultOkResponseSchema,
|
|
16
|
+
makeListDescription: ({ pluralLower }) => `Returns a paginated collection of ${pluralLower} scoped to the authenticated tenant.`
|
|
17
|
+
});
|
|
18
|
+
function createProgressCrudOpenApi(options) {
|
|
19
|
+
return buildProgressCrudOpenApi(options);
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
createPagedListResponseSchema,
|
|
23
|
+
createProgressCrudOpenApi,
|
|
24
|
+
defaultCreateResponseSchema,
|
|
25
|
+
defaultOkResponseSchema
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=openapi.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/progress/api/openapi.ts"],
|
|
4
|
+
"sourcesContent": ["import { type ZodTypeAny } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport {\n createCrudOpenApiFactory,\n createPagedListResponseSchema as createSharedPagedListResponseSchema,\n defaultCreateResponseSchema as sharedDefaultCreateResponseSchema,\n defaultOkResponseSchema as sharedDefaultOkResponseSchema,\n type CrudOpenApiOptions,\n} from '@open-mercato/shared/lib/openapi/crud'\n\nexport const defaultCreateResponseSchema = sharedDefaultCreateResponseSchema\nexport const defaultOkResponseSchema = sharedDefaultOkResponseSchema\n\nexport function createPagedListResponseSchema(itemSchema: ZodTypeAny) {\n return createSharedPagedListResponseSchema(itemSchema, { paginationMetaOptional: true })\n}\n\nconst buildProgressCrudOpenApi = createCrudOpenApiFactory({\n defaultTag: 'Progress',\n defaultCreateResponseSchema,\n defaultOkResponseSchema,\n makeListDescription: ({ pluralLower }) =>\n `Returns a paginated collection of ${pluralLower} scoped to the authenticated tenant.`,\n})\n\nexport function createProgressCrudOpenApi(options: CrudOpenApiOptions): OpenApiRouteDoc {\n return buildProgressCrudOpenApi(options)\n}\n"],
|
|
5
|
+
"mappings": "AAEA;AAAA,EACE;AAAA,EACA,iCAAiC;AAAA,EACjC,+BAA+B;AAAA,EAC/B,2BAA2B;AAAA,OAEtB;AAEA,MAAM,8BAA8B;AACpC,MAAM,0BAA0B;AAEhC,SAAS,8BAA8B,YAAwB;AACpE,SAAO,oCAAoC,YAAY,EAAE,wBAAwB,KAAK,CAAC;AACzF;AAEA,MAAM,2BAA2B,yBAAyB;AAAA,EACxD,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,qBAAqB,CAAC,EAAE,YAAY,MAClC,qCAAqC,WAAW;AACpD,CAAC;AAEM,SAAS,0BAA0B,SAA8C;AACtF,SAAO,yBAAyB,OAAO;AACzC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
import { Entity, PrimaryKey, Property, Index, OptionalProps } from "@mikro-orm/core";
|
|
12
|
+
OptionalProps;
|
|
13
|
+
let ProgressJob = class {
|
|
14
|
+
constructor() {
|
|
15
|
+
this.status = "pending";
|
|
16
|
+
this.progressPercent = 0;
|
|
17
|
+
this.processedCount = 0;
|
|
18
|
+
this.cancellable = false;
|
|
19
|
+
this.createdAt = /* @__PURE__ */ new Date();
|
|
20
|
+
this.updatedAt = /* @__PURE__ */ new Date();
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
__decorateClass([
|
|
24
|
+
PrimaryKey({ type: "uuid", defaultRaw: "gen_random_uuid()" })
|
|
25
|
+
], ProgressJob.prototype, "id", 2);
|
|
26
|
+
__decorateClass([
|
|
27
|
+
Property({ name: "job_type", type: "text" })
|
|
28
|
+
], ProgressJob.prototype, "jobType", 2);
|
|
29
|
+
__decorateClass([
|
|
30
|
+
Property({ name: "name", type: "text" })
|
|
31
|
+
], ProgressJob.prototype, "name", 2);
|
|
32
|
+
__decorateClass([
|
|
33
|
+
Property({ name: "description", type: "text", nullable: true })
|
|
34
|
+
], ProgressJob.prototype, "description", 2);
|
|
35
|
+
__decorateClass([
|
|
36
|
+
Property({ name: "status", type: "text" })
|
|
37
|
+
], ProgressJob.prototype, "status", 2);
|
|
38
|
+
__decorateClass([
|
|
39
|
+
Property({ name: "progress_percent", type: "smallint" })
|
|
40
|
+
], ProgressJob.prototype, "progressPercent", 2);
|
|
41
|
+
__decorateClass([
|
|
42
|
+
Property({ name: "processed_count", type: "int" })
|
|
43
|
+
], ProgressJob.prototype, "processedCount", 2);
|
|
44
|
+
__decorateClass([
|
|
45
|
+
Property({ name: "total_count", type: "int", nullable: true })
|
|
46
|
+
], ProgressJob.prototype, "totalCount", 2);
|
|
47
|
+
__decorateClass([
|
|
48
|
+
Property({ name: "eta_seconds", type: "int", nullable: true })
|
|
49
|
+
], ProgressJob.prototype, "etaSeconds", 2);
|
|
50
|
+
__decorateClass([
|
|
51
|
+
Property({ name: "started_by_user_id", type: "uuid", nullable: true })
|
|
52
|
+
], ProgressJob.prototype, "startedByUserId", 2);
|
|
53
|
+
__decorateClass([
|
|
54
|
+
Property({ name: "started_at", type: Date, nullable: true })
|
|
55
|
+
], ProgressJob.prototype, "startedAt", 2);
|
|
56
|
+
__decorateClass([
|
|
57
|
+
Property({ name: "heartbeat_at", type: Date, nullable: true })
|
|
58
|
+
], ProgressJob.prototype, "heartbeatAt", 2);
|
|
59
|
+
__decorateClass([
|
|
60
|
+
Property({ name: "finished_at", type: Date, nullable: true })
|
|
61
|
+
], ProgressJob.prototype, "finishedAt", 2);
|
|
62
|
+
__decorateClass([
|
|
63
|
+
Property({ name: "result_summary", type: "json", nullable: true })
|
|
64
|
+
], ProgressJob.prototype, "resultSummary", 2);
|
|
65
|
+
__decorateClass([
|
|
66
|
+
Property({ name: "error_message", type: "text", nullable: true })
|
|
67
|
+
], ProgressJob.prototype, "errorMessage", 2);
|
|
68
|
+
__decorateClass([
|
|
69
|
+
Property({ name: "error_stack", type: "text", nullable: true })
|
|
70
|
+
], ProgressJob.prototype, "errorStack", 2);
|
|
71
|
+
__decorateClass([
|
|
72
|
+
Property({ name: "meta", type: "json", nullable: true })
|
|
73
|
+
], ProgressJob.prototype, "meta", 2);
|
|
74
|
+
__decorateClass([
|
|
75
|
+
Property({ name: "cancellable", type: "boolean" })
|
|
76
|
+
], ProgressJob.prototype, "cancellable", 2);
|
|
77
|
+
__decorateClass([
|
|
78
|
+
Property({ name: "cancelled_by_user_id", type: "uuid", nullable: true })
|
|
79
|
+
], ProgressJob.prototype, "cancelledByUserId", 2);
|
|
80
|
+
__decorateClass([
|
|
81
|
+
Property({ name: "cancel_requested_at", type: Date, nullable: true })
|
|
82
|
+
], ProgressJob.prototype, "cancelRequestedAt", 2);
|
|
83
|
+
__decorateClass([
|
|
84
|
+
Property({ name: "parent_job_id", type: "uuid", nullable: true })
|
|
85
|
+
], ProgressJob.prototype, "parentJobId", 2);
|
|
86
|
+
__decorateClass([
|
|
87
|
+
Property({ name: "partition_index", type: "int", nullable: true })
|
|
88
|
+
], ProgressJob.prototype, "partitionIndex", 2);
|
|
89
|
+
__decorateClass([
|
|
90
|
+
Property({ name: "partition_count", type: "int", nullable: true })
|
|
91
|
+
], ProgressJob.prototype, "partitionCount", 2);
|
|
92
|
+
__decorateClass([
|
|
93
|
+
Property({ name: "tenant_id", type: "uuid" })
|
|
94
|
+
], ProgressJob.prototype, "tenantId", 2);
|
|
95
|
+
__decorateClass([
|
|
96
|
+
Property({ name: "organization_id", type: "uuid", nullable: true })
|
|
97
|
+
], ProgressJob.prototype, "organizationId", 2);
|
|
98
|
+
__decorateClass([
|
|
99
|
+
Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
|
|
100
|
+
], ProgressJob.prototype, "createdAt", 2);
|
|
101
|
+
__decorateClass([
|
|
102
|
+
Property({ name: "updated_at", type: Date, onUpdate: () => /* @__PURE__ */ new Date() })
|
|
103
|
+
], ProgressJob.prototype, "updatedAt", 2);
|
|
104
|
+
ProgressJob = __decorateClass([
|
|
105
|
+
Entity({ tableName: "progress_jobs" }),
|
|
106
|
+
Index({ name: "progress_jobs_status_tenant_idx", properties: ["status", "tenantId"] }),
|
|
107
|
+
Index({ name: "progress_jobs_type_tenant_idx", properties: ["jobType", "tenantId"] }),
|
|
108
|
+
Index({ name: "progress_jobs_parent_idx", properties: ["parentJobId"] })
|
|
109
|
+
], ProgressJob);
|
|
110
|
+
export {
|
|
111
|
+
ProgressJob
|
|
112
|
+
};
|
|
113
|
+
//# sourceMappingURL=entities.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/progress/data/entities.ts"],
|
|
4
|
+
"sourcesContent": ["import { Entity, PrimaryKey, Property, Index, OptionalProps } from '@mikro-orm/core'\n\nexport type ProgressJobStatus = 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n\n// No deleted_at column: terminal statuses (completed, failed, cancelled) serve as logical soft-delete.\n// Old jobs should be purged via scheduled cleanup rather than soft-deleted individually.\n@Entity({ tableName: 'progress_jobs' })\n@Index({ name: 'progress_jobs_status_tenant_idx', properties: ['status', 'tenantId'] })\n@Index({ name: 'progress_jobs_type_tenant_idx', properties: ['jobType', 'tenantId'] })\n@Index({ name: 'progress_jobs_parent_idx', properties: ['parentJobId'] })\nexport class ProgressJob {\n [OptionalProps]?: 'status' | 'progressPercent' | 'processedCount' | 'cancellable' | 'createdAt' | 'updatedAt'\n\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'job_type', type: 'text' })\n jobType!: string\n\n @Property({ name: 'name', type: 'text' })\n name!: string\n\n @Property({ name: 'description', type: 'text', nullable: true })\n description?: string | null\n\n @Property({ name: 'status', type: 'text' })\n status: ProgressJobStatus = 'pending'\n\n @Property({ name: 'progress_percent', type: 'smallint' })\n progressPercent: number = 0\n\n @Property({ name: 'processed_count', type: 'int' })\n processedCount: number = 0\n\n @Property({ name: 'total_count', type: 'int', nullable: true })\n totalCount?: number | null\n\n @Property({ name: 'eta_seconds', type: 'int', nullable: true })\n etaSeconds?: number | null\n\n @Property({ name: 'started_by_user_id', type: 'uuid', nullable: true })\n startedByUserId?: string | null\n\n @Property({ name: 'started_at', type: Date, nullable: true })\n startedAt?: Date | null\n\n @Property({ name: 'heartbeat_at', type: Date, nullable: true })\n heartbeatAt?: Date | null\n\n @Property({ name: 'finished_at', type: Date, nullable: true })\n finishedAt?: Date | null\n\n @Property({ name: 'result_summary', type: 'json', nullable: true })\n resultSummary?: Record<string, unknown> | null\n\n @Property({ name: 'error_message', type: 'text', nullable: true })\n errorMessage?: string | null\n\n @Property({ name: 'error_stack', type: 'text', nullable: true })\n errorStack?: string | null\n\n @Property({ name: 'meta', type: 'json', nullable: true })\n meta?: Record<string, unknown> | null\n\n @Property({ name: 'cancellable', type: 'boolean' })\n cancellable: boolean = false\n\n @Property({ name: 'cancelled_by_user_id', type: 'uuid', nullable: true })\n cancelledByUserId?: string | null\n\n @Property({ name: 'cancel_requested_at', type: Date, nullable: true })\n cancelRequestedAt?: Date | null\n\n @Property({ name: 'parent_job_id', type: 'uuid', nullable: true })\n parentJobId?: string | null\n\n @Property({ name: 'partition_index', type: 'int', nullable: true })\n partitionIndex?: number | null\n\n @Property({ name: 'partition_count', type: 'int', nullable: true })\n partitionCount?: number | null\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'organization_id', type: 'uuid', nullable: true })\n organizationId?: string | null\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const progressJobStatusSchema = z.enum(["pending", "running", "completed", "failed", "cancelled"]);
|
|
3
|
+
const createProgressJobSchema = z.object({
|
|
4
|
+
jobType: z.string().min(1).max(100),
|
|
5
|
+
name: z.string().min(1).max(255),
|
|
6
|
+
description: z.string().max(1e3).optional(),
|
|
7
|
+
totalCount: z.number().int().positive().optional(),
|
|
8
|
+
cancellable: z.boolean().optional().default(false),
|
|
9
|
+
meta: z.record(z.string(), z.unknown()).optional(),
|
|
10
|
+
parentJobId: z.string().uuid().optional(),
|
|
11
|
+
partitionIndex: z.number().int().min(0).optional(),
|
|
12
|
+
partitionCount: z.number().int().positive().optional()
|
|
13
|
+
});
|
|
14
|
+
const updateProgressSchema = z.object({
|
|
15
|
+
processedCount: z.number().int().min(0).optional(),
|
|
16
|
+
progressPercent: z.number().int().min(0).max(100).optional(),
|
|
17
|
+
totalCount: z.number().int().positive().optional(),
|
|
18
|
+
etaSeconds: z.number().int().min(0).optional(),
|
|
19
|
+
meta: z.record(z.string(), z.unknown()).optional()
|
|
20
|
+
});
|
|
21
|
+
const completeJobSchema = z.object({
|
|
22
|
+
resultSummary: z.record(z.string(), z.unknown()).optional()
|
|
23
|
+
});
|
|
24
|
+
const failJobSchema = z.object({
|
|
25
|
+
errorMessage: z.string().max(2e3),
|
|
26
|
+
errorStack: z.string().max(1e4).optional()
|
|
27
|
+
});
|
|
28
|
+
const listProgressJobsSchema = z.object({
|
|
29
|
+
status: z.string().optional(),
|
|
30
|
+
jobType: z.string().optional(),
|
|
31
|
+
parentJobId: z.string().uuid().optional(),
|
|
32
|
+
includeCompleted: z.enum(["true", "false"]).optional(),
|
|
33
|
+
completedSince: z.string().optional(),
|
|
34
|
+
page: z.coerce.number().min(1).default(1),
|
|
35
|
+
pageSize: z.coerce.number().min(1).max(100).default(20),
|
|
36
|
+
search: z.string().optional(),
|
|
37
|
+
sortField: z.enum(["createdAt", "startedAt", "finishedAt"]).optional(),
|
|
38
|
+
sortDir: z.enum(["asc", "desc"]).optional()
|
|
39
|
+
});
|
|
40
|
+
export {
|
|
41
|
+
completeJobSchema,
|
|
42
|
+
createProgressJobSchema,
|
|
43
|
+
failJobSchema,
|
|
44
|
+
listProgressJobsSchema,
|
|
45
|
+
progressJobStatusSchema,
|
|
46
|
+
updateProgressSchema
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/progress/data/validators.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\n\nexport const progressJobStatusSchema = z.enum(['pending', 'running', 'completed', 'failed', 'cancelled'])\n\nexport const createProgressJobSchema = z.object({\n jobType: z.string().min(1).max(100),\n name: z.string().min(1).max(255),\n description: z.string().max(1000).optional(),\n totalCount: z.number().int().positive().optional(),\n cancellable: z.boolean().optional().default(false),\n meta: z.record(z.string(), z.unknown()).optional(),\n parentJobId: z.string().uuid().optional(),\n partitionIndex: z.number().int().min(0).optional(),\n partitionCount: z.number().int().positive().optional(),\n})\n\nexport const updateProgressSchema = z.object({\n processedCount: z.number().int().min(0).optional(),\n progressPercent: z.number().int().min(0).max(100).optional(),\n totalCount: z.number().int().positive().optional(),\n etaSeconds: z.number().int().min(0).optional(),\n meta: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const completeJobSchema = z.object({\n resultSummary: z.record(z.string(), z.unknown()).optional(),\n})\n\nexport const failJobSchema = z.object({\n errorMessage: z.string().max(2000),\n errorStack: z.string().max(10000).optional(),\n})\n\nexport const listProgressJobsSchema = z.object({\n status: z.string().optional(),\n jobType: z.string().optional(),\n parentJobId: z.string().uuid().optional(),\n includeCompleted: z.enum(['true', 'false']).optional(),\n completedSince: z.string().optional(),\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(20),\n search: z.string().optional(),\n sortField: z.enum(['createdAt', 'startedAt', 'finishedAt']).optional(),\n sortDir: z.enum(['asc', 'desc']).optional(),\n})\n\nexport type CreateProgressJobInput = z.infer<typeof createProgressJobSchema>\nexport type UpdateProgressInput = z.infer<typeof updateProgressSchema>\nexport type CompleteJobInput = z.infer<typeof completeJobSchema>\nexport type FailJobInput = z.infer<typeof failJobSchema>\nexport type ListProgressJobsInput = z.infer<typeof listProgressJobsSchema>\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAEX,MAAM,0BAA0B,EAAE,KAAK,CAAC,WAAW,WAAW,aAAa,UAAU,WAAW,CAAC;AAEjG,MAAM,0BAA0B,EAAE,OAAO;AAAA,EAC9C,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAClC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,EAC/B,aAAa,EAAE,OAAO,EAAE,IAAI,GAAI,EAAE,SAAS;AAAA,EAC3C,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,KAAK;AAAA,EACjD,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS;AAAA,EACjD,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACxC,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACjD,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AACvD,CAAC;AAEM,MAAM,uBAAuB,EAAE,OAAO;AAAA,EAC3C,gBAAgB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EACjD,iBAAiB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,SAAS;AAAA,EAC3D,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS;AAAA,EACjD,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC7C,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS;AACnD,CAAC;AAEM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,eAAe,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,EAAE,SAAS;AAC5D,CAAC;AAEM,MAAM,gBAAgB,EAAE,OAAO;AAAA,EACpC,cAAc,EAAE,OAAO,EAAE,IAAI,GAAI;AAAA,EACjC,YAAY,EAAE,OAAO,EAAE,IAAI,GAAK,EAAE,SAAS;AAC7C,CAAC;AAEM,MAAM,yBAAyB,EAAE,OAAO;AAAA,EAC7C,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACxC,kBAAkB,EAAE,KAAK,CAAC,QAAQ,OAAO,CAAC,EAAE,SAAS;AAAA,EACrD,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,EACpC,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EACxC,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAAA,EACtD,QAAQ,EAAE,OAAO,EAAE,SAAS;AAAA,EAC5B,WAAW,EAAE,KAAK,CAAC,aAAa,aAAa,YAAY,CAAC,EAAE,SAAS;AAAA,EACrE,SAAS,EAAE,KAAK,CAAC,OAAO,MAAM,CAAC,EAAE,SAAS;AAC5C,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { createProgressService } from "./lib/progressServiceImpl.js";
|
|
2
|
+
function register(container) {
|
|
3
|
+
container.register({
|
|
4
|
+
progressService: {
|
|
5
|
+
resolve: (c) => {
|
|
6
|
+
const em = c.resolve("em");
|
|
7
|
+
const eventBus = c.resolve("eventBus");
|
|
8
|
+
return createProgressService(em, eventBus);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
export {
|
|
14
|
+
register
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=di.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/progress/di.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/core'\nimport { createProgressService } from './lib/progressServiceImpl'\n\nexport function register(container: AppContainer) {\n container.register({\n progressService: {\n resolve: (c) => {\n const em = c.resolve<EntityManager>('em')\n const eventBus = c.resolve('eventBus') as { emit: (event: string, payload: Record<string, unknown>) => Promise<void> }\n return createProgressService(em, eventBus)\n },\n },\n })\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,6BAA6B;AAE/B,SAAS,SAAS,WAAyB;AAChD,YAAU,SAAS;AAAA,IACjB,iBAAiB;AAAA,MACf,SAAS,CAAC,MAAM;AACd,cAAM,KAAK,EAAE,QAAuB,IAAI;AACxC,cAAM,WAAW,EAAE,QAAQ,UAAU;AACrC,eAAO,sBAAsB,IAAI,QAAQ;AAAA,MAC3C;AAAA,IACF;AAAA,EACF,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createModuleEvents } from "@open-mercato/shared/modules/events";
|
|
2
|
+
const events = [
|
|
3
|
+
{ id: "progress.job.created", label: "Job Created", entity: "job", category: "crud" },
|
|
4
|
+
{ id: "progress.job.started", label: "Job Started", entity: "job", category: "lifecycle" },
|
|
5
|
+
{ id: "progress.job.updated", label: "Job Updated", entity: "job", category: "lifecycle" },
|
|
6
|
+
{ id: "progress.job.completed", label: "Job Completed", entity: "job", category: "lifecycle" },
|
|
7
|
+
{ id: "progress.job.failed", label: "Job Failed", entity: "job", category: "lifecycle" },
|
|
8
|
+
{ id: "progress.job.cancelled", label: "Job Cancelled", entity: "job", category: "lifecycle" }
|
|
9
|
+
];
|
|
10
|
+
const eventsConfig = createModuleEvents({
|
|
11
|
+
moduleId: "progress",
|
|
12
|
+
events
|
|
13
|
+
});
|
|
14
|
+
const emitProgressEvent = eventsConfig.emit;
|
|
15
|
+
var events_default = eventsConfig;
|
|
16
|
+
export {
|
|
17
|
+
events_default as default,
|
|
18
|
+
emitProgressEvent,
|
|
19
|
+
events,
|
|
20
|
+
eventsConfig
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/progress/events.ts"],
|
|
4
|
+
"sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\nexport const events = [\n { id: 'progress.job.created', label: 'Job Created', entity: 'job', category: 'crud' },\n { id: 'progress.job.started', label: 'Job Started', entity: 'job', category: 'lifecycle' },\n { id: 'progress.job.updated', label: 'Job Updated', entity: 'job', category: 'lifecycle' },\n { id: 'progress.job.completed', label: 'Job Completed', entity: 'job', category: 'lifecycle' },\n { id: 'progress.job.failed', label: 'Job Failed', entity: 'job', category: 'lifecycle' },\n { id: 'progress.job.cancelled', label: 'Job Cancelled', entity: 'job', category: 'lifecycle' },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'progress',\n events,\n})\n\nexport const emitProgressEvent = eventsConfig.emit\n\nexport type ProgressEventId = typeof events[number]['id']\n\nexport default eventsConfig\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,0BAA0B;AAE5B,MAAM,SAAS;AAAA,EACpB,EAAE,IAAI,wBAAwB,OAAO,eAAe,QAAQ,OAAO,UAAU,OAAO;AAAA,EACpF,EAAE,IAAI,wBAAwB,OAAO,eAAe,QAAQ,OAAO,UAAU,YAAY;AAAA,EACzF,EAAE,IAAI,wBAAwB,OAAO,eAAe,QAAQ,OAAO,UAAU,YAAY;AAAA,EACzF,EAAE,IAAI,0BAA0B,OAAO,iBAAiB,QAAQ,OAAO,UAAU,YAAY;AAAA,EAC7F,EAAE,IAAI,uBAAuB,OAAO,cAAc,QAAQ,OAAO,UAAU,YAAY;AAAA,EACvF,EAAE,IAAI,0BAA0B,OAAO,iBAAiB,QAAQ,OAAO,UAAU,YAAY;AAC/F;AAEO,MAAM,eAAe,mBAAmB;AAAA,EAC7C,UAAU;AAAA,EACV;AACF,CAAC;AAEM,MAAM,oBAAoB,aAAa;AAI9C,IAAO,iBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const metadata = {
|
|
2
|
+
name: "progress",
|
|
3
|
+
title: "Progress",
|
|
4
|
+
version: "0.1.0",
|
|
5
|
+
description: "Generic server-side progress tracking for long-running operations",
|
|
6
|
+
author: "Open Mercato Team",
|
|
7
|
+
license: "Proprietary",
|
|
8
|
+
ejectable: true
|
|
9
|
+
};
|
|
10
|
+
export {
|
|
11
|
+
metadata
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/progress/index.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ModuleInfo } from '@open-mercato/shared/modules/registry'\n\nexport const metadata: ModuleInfo = {\n name: 'progress',\n title: 'Progress',\n version: '0.1.0',\n description: 'Generic server-side progress tracking for long-running operations',\n author: 'Open Mercato Team',\n license: 'Proprietary',\n ejectable: true,\n}\n"],
|
|
5
|
+
"mappings": "AAEO,MAAM,WAAuB;AAAA,EAClC,MAAM;AAAA,EACN,OAAO;AAAA,EACP,SAAS;AAAA,EACT,aAAa;AAAA,EACb,QAAQ;AAAA,EACR,SAAS;AAAA,EACT,WAAW;AACb;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { events } from "../events.js";
|
|
2
|
+
function buildEventMap(defs) {
|
|
3
|
+
const map = {};
|
|
4
|
+
for (const def of defs) {
|
|
5
|
+
const suffix = def.id.replace("progress.job.", "");
|
|
6
|
+
map[`JOB_${suffix.toUpperCase()}`] = def.id;
|
|
7
|
+
}
|
|
8
|
+
return map;
|
|
9
|
+
}
|
|
10
|
+
const PROGRESS_EVENTS = buildEventMap(events);
|
|
11
|
+
export {
|
|
12
|
+
PROGRESS_EVENTS
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/progress/lib/events.ts"],
|
|
4
|
+
"sourcesContent": ["import { events } from '../events'\n\ntype EventEntry = typeof events[number]\ntype EventMap = { [K in EventEntry['id'] as Uppercase<K extends `progress.job.${infer A}` ? `JOB_${A}` : never>]: K }\n\nfunction buildEventMap<T extends readonly { id: string }[]>(defs: T) {\n const map: Record<string, string> = {}\n for (const def of defs) {\n const suffix = def.id.replace('progress.job.', '')\n map[`JOB_${suffix.toUpperCase()}`] = def.id\n }\n return map as EventMap\n}\n\nexport const PROGRESS_EVENTS = buildEventMap(events)\n\nexport type ProgressJobCreatedPayload = {\n jobId: string\n jobType: string\n name: string\n tenantId: string\n organizationId?: string | null\n}\n\nexport type ProgressJobStartedPayload = {\n jobId: string\n jobType: string\n tenantId: string\n}\n\nexport type ProgressJobUpdatedPayload = {\n jobId: string\n jobType?: string\n progressPercent: number\n processedCount: number\n totalCount?: number | null\n etaSeconds?: number | null\n tenantId: string\n}\n\nexport type ProgressJobCompletedPayload = {\n jobId: string\n jobType: string\n resultSummary?: Record<string, unknown> | null\n tenantId: string\n}\n\nexport type ProgressJobFailedPayload = {\n jobId: string\n jobType: string\n errorMessage: string\n tenantId: string\n stale?: boolean\n}\n\nexport type ProgressJobCancelledPayload = {\n jobId: string\n jobType: string\n tenantId: string\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,cAAc;AAKvB,SAAS,cAAmD,MAAS;AACnE,QAAM,MAA8B,CAAC;AACrC,aAAW,OAAO,MAAM;AACtB,UAAM,SAAS,IAAI,GAAG,QAAQ,iBAAiB,EAAE;AACjD,QAAI,OAAO,OAAO,YAAY,CAAC,EAAE,IAAI,IAAI;AAAA,EAC3C;AACA,SAAO;AACT;AAEO,MAAM,kBAAkB,cAAc,MAAM;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
const HEARTBEAT_INTERVAL_MS = 5e3;
|
|
2
|
+
const STALE_JOB_TIMEOUT_SECONDS = 60;
|
|
3
|
+
function calculateEta(processedCount, totalCount, startedAt) {
|
|
4
|
+
if (processedCount === 0 || totalCount === 0) return null;
|
|
5
|
+
const elapsedMs = Date.now() - startedAt.getTime();
|
|
6
|
+
const rate = processedCount / elapsedMs;
|
|
7
|
+
const remaining = totalCount - processedCount;
|
|
8
|
+
if (rate <= 0) return null;
|
|
9
|
+
return Math.ceil(remaining / rate / 1e3);
|
|
10
|
+
}
|
|
11
|
+
function calculateProgressPercent(processedCount, totalCount) {
|
|
12
|
+
if (!totalCount || totalCount <= 0) return 0;
|
|
13
|
+
return Math.min(100, Math.round(processedCount / totalCount * 100));
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
HEARTBEAT_INTERVAL_MS,
|
|
17
|
+
STALE_JOB_TIMEOUT_SECONDS,
|
|
18
|
+
calculateEta,
|
|
19
|
+
calculateProgressPercent
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=progressService.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/progress/lib/progressService.ts"],
|
|
4
|
+
"sourcesContent": ["import type { ProgressJob } from '../data/entities'\nimport type { CreateProgressJobInput, UpdateProgressInput, CompleteJobInput, FailJobInput } from '../data/validators'\n\nexport interface ProgressServiceContext {\n tenantId: string\n organizationId?: string | null\n userId?: string | null\n}\n\nexport interface ProgressService {\n createJob(input: CreateProgressJobInput, ctx: ProgressServiceContext): Promise<ProgressJob>\n startJob(jobId: string, ctx: ProgressServiceContext): Promise<ProgressJob>\n updateProgress(jobId: string, input: UpdateProgressInput, ctx: ProgressServiceContext): Promise<ProgressJob>\n incrementProgress(jobId: string, delta: number, ctx: ProgressServiceContext): Promise<ProgressJob>\n completeJob(jobId: string, input: CompleteJobInput | undefined, ctx: ProgressServiceContext): Promise<ProgressJob>\n failJob(jobId: string, input: FailJobInput, ctx: ProgressServiceContext): Promise<ProgressJob>\n cancelJob(jobId: string, ctx: ProgressServiceContext): Promise<ProgressJob>\n isCancellationRequested(jobId: string): Promise<boolean>\n getActiveJobs(ctx: ProgressServiceContext): Promise<ProgressJob[]>\n getRecentlyCompletedJobs(ctx: ProgressServiceContext, sinceSeconds?: number): Promise<ProgressJob[]>\n getJob(jobId: string, ctx: ProgressServiceContext): Promise<ProgressJob | null>\n markStaleJobsFailed(tenantId: string, timeoutSeconds?: number): Promise<number>\n}\n\nexport const HEARTBEAT_INTERVAL_MS = 5000\nexport const STALE_JOB_TIMEOUT_SECONDS = 60\n\nexport function calculateEta(\n processedCount: number,\n totalCount: number,\n startedAt: Date,\n): number | null {\n if (processedCount === 0 || totalCount === 0) return null\n\n const elapsedMs = Date.now() - startedAt.getTime()\n const rate = processedCount / elapsedMs\n const remaining = totalCount - processedCount\n\n if (rate <= 0) return null\n\n return Math.ceil(remaining / rate / 1000)\n}\n\nexport function calculateProgressPercent(processedCount: number, totalCount: number | null): number {\n if (!totalCount || totalCount <= 0) return 0\n return Math.min(100, Math.round((processedCount / totalCount) * 100))\n}\n"],
|
|
5
|
+
"mappings": "AAwBO,MAAM,wBAAwB;AAC9B,MAAM,4BAA4B;AAElC,SAAS,aACd,gBACA,YACA,WACe;AACf,MAAI,mBAAmB,KAAK,eAAe,EAAG,QAAO;AAErD,QAAM,YAAY,KAAK,IAAI,IAAI,UAAU,QAAQ;AACjD,QAAM,OAAO,iBAAiB;AAC9B,QAAM,YAAY,aAAa;AAE/B,MAAI,QAAQ,EAAG,QAAO;AAEtB,SAAO,KAAK,KAAK,YAAY,OAAO,GAAI;AAC1C;AAEO,SAAS,yBAAyB,gBAAwB,YAAmC;AAClG,MAAI,CAAC,cAAc,cAAc,EAAG,QAAO;AAC3C,SAAO,KAAK,IAAI,KAAK,KAAK,MAAO,iBAAiB,aAAc,GAAG,CAAC;AACtE;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|