@deenruv/replicate-plugin 1.0.0
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/LICENSE +23 -0
- package/README.md +43 -0
- package/dist/plugin-server/constants.d.ts +2 -0
- package/dist/plugin-server/constants.js +5 -0
- package/dist/plugin-server/controllers/replicate.d.ts +22 -0
- package/dist/plugin-server/controllers/replicate.js +56 -0
- package/dist/plugin-server/e2e/order-export.e2e.test.d.ts +1 -0
- package/dist/plugin-server/e2e/order-export.e2e.test.js +163 -0
- package/dist/plugin-server/e2e/with-token.e2e.test.d.ts +1 -0
- package/dist/plugin-server/e2e/with-token.e2e.test.js +72 -0
- package/dist/plugin-server/e2e/without-token.e2e.test.d.ts +1 -0
- package/dist/plugin-server/e2e/without-token.e2e.test.js +75 -0
- package/dist/plugin-server/entites/replicate.entity.d.ts +13 -0
- package/dist/plugin-server/entites/replicate.entity.js +41 -0
- package/dist/plugin-server/extensions/replicate.extension.d.ts +1 -0
- package/dist/plugin-server/extensions/replicate.extension.js +78 -0
- package/dist/plugin-server/graphql/generated-admin-types.d.ts +5847 -0
- package/dist/plugin-server/graphql/generated-admin-types.js +1036 -0
- package/dist/plugin-server/index.d.ts +5 -0
- package/dist/plugin-server/index.js +42 -0
- package/dist/plugin-server/resolvers/replicate-admin.resolver.d.ts +35 -0
- package/dist/plugin-server/resolvers/replicate-admin.resolver.js +84 -0
- package/dist/plugin-server/services/replicate.service.d.ts +43 -0
- package/dist/plugin-server/services/replicate.service.js +389 -0
- package/dist/plugin-server/types.d.ts +19 -0
- package/dist/plugin-server/types.js +2 -0
- package/dist/plugin-server/zeus/const.d.ts +6 -0
- package/dist/plugin-server/zeus/const.js +3777 -0
- package/dist/plugin-server/zeus/index.d.ts +19250 -0
- package/dist/plugin-server/zeus/index.js +1104 -0
- package/dist/plugin-server/zeus/typedDocumentNode.d.ts +3 -0
- package/dist/plugin-server/zeus/typedDocumentNode.js +13 -0
- package/dist/plugin-ui/components/Replicate.d.ts +2 -0
- package/dist/plugin-ui/components/Replicate.js +307 -0
- package/dist/plugin-ui/components/ReplicateUtilities.d.ts +4 -0
- package/dist/plugin-ui/components/ReplicateUtilities.js +57 -0
- package/dist/plugin-ui/components/index.d.ts +1 -0
- package/dist/plugin-ui/components/index.js +1 -0
- package/dist/plugin-ui/graphql/mutations.d.ts +11 -0
- package/dist/plugin-ui/graphql/mutations.js +11 -0
- package/dist/plugin-ui/graphql/queries.d.ts +73 -0
- package/dist/plugin-ui/graphql/queries.js +30 -0
- package/dist/plugin-ui/graphql/selectors.d.ts +24 -0
- package/dist/plugin-ui/graphql/selectors.js +17 -0
- package/dist/plugin-ui/index.d.ts +1 -0
- package/dist/plugin-ui/index.js +25 -0
- package/dist/plugin-ui/locales/en/badges.json +25 -0
- package/dist/plugin-ui/locales/en/index.d.ts +26 -0
- package/dist/plugin-ui/locales/en/index.js +2 -0
- package/dist/plugin-ui/locales/pl/badges.json +25 -0
- package/dist/plugin-ui/locales/pl/index.d.ts +26 -0
- package/dist/plugin-ui/locales/pl/index.js +2 -0
- package/dist/plugin-ui/translation-ns.d.ts +1 -0
- package/dist/plugin-ui/translation-ns.js +1 -0
- package/dist/plugin-ui/tsconfig.json +18 -0
- package/dist/plugin-ui/zeus/const.d.ts +6 -0
- package/dist/plugin-ui/zeus/const.js +3774 -0
- package/dist/plugin-ui/zeus/index.d.ts +19250 -0
- package/dist/plugin-ui/zeus/index.js +1096 -0
- package/dist/plugin-ui/zeus/typedDocumentNode.d.ts +3 -0
- package/dist/plugin-ui/zeus/typedDocumentNode.js +9 -0
- package/package.json +54 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.ReplicatePlugin = void 0;
|
|
10
|
+
const core_1 = require("@deenruv/core");
|
|
11
|
+
const replicate_admin_resolver_js_1 = require("./resolvers/replicate-admin.resolver.js");
|
|
12
|
+
const replicate_service_js_1 = require("./services/replicate.service.js");
|
|
13
|
+
const replicate_js_1 = require("./controllers/replicate.js");
|
|
14
|
+
const constants_js_1 = require("./constants.js");
|
|
15
|
+
const replicate_extension_js_1 = require("./extensions/replicate.extension.js");
|
|
16
|
+
const replicate_entity_js_1 = require("./entites/replicate.entity.js");
|
|
17
|
+
let ReplicatePlugin = class ReplicatePlugin {
|
|
18
|
+
static init(options) {
|
|
19
|
+
this.options = options;
|
|
20
|
+
return this;
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
exports.ReplicatePlugin = ReplicatePlugin;
|
|
24
|
+
exports.ReplicatePlugin = ReplicatePlugin = __decorate([
|
|
25
|
+
(0, core_1.DeenruvPlugin)({
|
|
26
|
+
compatibility: "^0.0.20",
|
|
27
|
+
imports: [core_1.PluginCommonModule],
|
|
28
|
+
entities: [replicate_entity_js_1.ReplicateEntity],
|
|
29
|
+
providers: [
|
|
30
|
+
{
|
|
31
|
+
provide: constants_js_1.REPLICATE_PLUGIN_OPTIONS,
|
|
32
|
+
useFactory: () => ReplicatePlugin.options,
|
|
33
|
+
},
|
|
34
|
+
replicate_service_js_1.ReplicateService,
|
|
35
|
+
],
|
|
36
|
+
controllers: [replicate_js_1.ReplicateController],
|
|
37
|
+
adminApiExtensions: {
|
|
38
|
+
schema: replicate_extension_js_1.AdminExtension,
|
|
39
|
+
resolvers: [replicate_admin_resolver_js_1.ReplicateAdminResolver],
|
|
40
|
+
},
|
|
41
|
+
})
|
|
42
|
+
], ReplicatePlugin);
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ReplicateService } from "../services/replicate.service.js";
|
|
2
|
+
import { RequestContext, Customer } from "@deenruv/core";
|
|
3
|
+
import { StartOrderExportToReplicateInput } from "../graphql/generated-admin-types.js";
|
|
4
|
+
export declare class ReplicateAdminResolver {
|
|
5
|
+
private replicateService;
|
|
6
|
+
constructor(replicateService: ReplicateService);
|
|
7
|
+
startModelTraining({ input, }: {
|
|
8
|
+
input: {
|
|
9
|
+
numLastOrder: number;
|
|
10
|
+
startDate: string;
|
|
11
|
+
endDate: string;
|
|
12
|
+
};
|
|
13
|
+
}, ctx: RequestContext): Promise<string>;
|
|
14
|
+
startOrderExportToReplicate({ input }: {
|
|
15
|
+
input: StartOrderExportToReplicateInput;
|
|
16
|
+
}, ctx: RequestContext): Promise<import("@deenruv/core").ID>;
|
|
17
|
+
getPredictionID(ctx: RequestContext, { input }: {
|
|
18
|
+
input: {
|
|
19
|
+
prediction_entity_id: string;
|
|
20
|
+
};
|
|
21
|
+
}): Promise<string | undefined>;
|
|
22
|
+
getReplicatePredictions(ctx: RequestContext, { options }: {
|
|
23
|
+
options: any;
|
|
24
|
+
}): Promise<import("@deenruv/core").PaginatedList<import("../entites/replicate.entity.js").ReplicateEntity>>;
|
|
25
|
+
getPredictionItem(ctx: RequestContext, { id }: {
|
|
26
|
+
id: string;
|
|
27
|
+
}): Promise<{
|
|
28
|
+
status: string;
|
|
29
|
+
predictions: {
|
|
30
|
+
id: import("@deenruv/core").ID;
|
|
31
|
+
score: number;
|
|
32
|
+
customer: Customer | null;
|
|
33
|
+
}[];
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.ReplicateAdminResolver = void 0;
|
|
16
|
+
const graphql_1 = require("@nestjs/graphql");
|
|
17
|
+
const replicate_service_js_1 = require("../services/replicate.service.js");
|
|
18
|
+
const core_1 = require("@deenruv/core");
|
|
19
|
+
let ReplicateAdminResolver = class ReplicateAdminResolver {
|
|
20
|
+
constructor(replicateService) {
|
|
21
|
+
this.replicateService = replicateService;
|
|
22
|
+
}
|
|
23
|
+
async startModelTraining({ input, }, ctx) {
|
|
24
|
+
await this.replicateService.modelTrainingJob(ctx, input);
|
|
25
|
+
return "model training done";
|
|
26
|
+
}
|
|
27
|
+
async startOrderExportToReplicate({ input }, ctx) {
|
|
28
|
+
return this.replicateService.orderExportJob(ctx, input);
|
|
29
|
+
}
|
|
30
|
+
async getPredictionID(ctx, { input }) {
|
|
31
|
+
return this.replicateService.getPredictionID(ctx, input.prediction_entity_id);
|
|
32
|
+
}
|
|
33
|
+
async getReplicatePredictions(ctx, { options }) {
|
|
34
|
+
return this.replicateService.getPredictionItems(ctx, options);
|
|
35
|
+
}
|
|
36
|
+
async getPredictionItem(ctx, { id }) {
|
|
37
|
+
return this.replicateService.getPredictionItem(ctx, id);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
exports.ReplicateAdminResolver = ReplicateAdminResolver;
|
|
41
|
+
__decorate([
|
|
42
|
+
(0, graphql_1.Mutation)(),
|
|
43
|
+
__param(0, (0, graphql_1.Args)()),
|
|
44
|
+
__param(1, (0, core_1.Ctx)()),
|
|
45
|
+
__metadata("design:type", Function),
|
|
46
|
+
__metadata("design:paramtypes", [Object, core_1.RequestContext]),
|
|
47
|
+
__metadata("design:returntype", Promise)
|
|
48
|
+
], ReplicateAdminResolver.prototype, "startModelTraining", null);
|
|
49
|
+
__decorate([
|
|
50
|
+
(0, graphql_1.Mutation)(),
|
|
51
|
+
__param(0, (0, graphql_1.Args)()),
|
|
52
|
+
__param(1, (0, core_1.Ctx)()),
|
|
53
|
+
__metadata("design:type", Function),
|
|
54
|
+
__metadata("design:paramtypes", [Object, core_1.RequestContext]),
|
|
55
|
+
__metadata("design:returntype", Promise)
|
|
56
|
+
], ReplicateAdminResolver.prototype, "startOrderExportToReplicate", null);
|
|
57
|
+
__decorate([
|
|
58
|
+
(0, graphql_1.Query)(),
|
|
59
|
+
__param(0, (0, core_1.Ctx)()),
|
|
60
|
+
__param(1, (0, graphql_1.Args)()),
|
|
61
|
+
__metadata("design:type", Function),
|
|
62
|
+
__metadata("design:paramtypes", [core_1.RequestContext, Object]),
|
|
63
|
+
__metadata("design:returntype", Promise)
|
|
64
|
+
], ReplicateAdminResolver.prototype, "getPredictionID", null);
|
|
65
|
+
__decorate([
|
|
66
|
+
(0, graphql_1.Query)(),
|
|
67
|
+
__param(0, (0, core_1.Ctx)()),
|
|
68
|
+
__param(1, (0, graphql_1.Args)()),
|
|
69
|
+
__metadata("design:type", Function),
|
|
70
|
+
__metadata("design:paramtypes", [core_1.RequestContext, Object]),
|
|
71
|
+
__metadata("design:returntype", Promise)
|
|
72
|
+
], ReplicateAdminResolver.prototype, "getReplicatePredictions", null);
|
|
73
|
+
__decorate([
|
|
74
|
+
(0, graphql_1.Query)(),
|
|
75
|
+
__param(0, (0, core_1.Ctx)()),
|
|
76
|
+
__param(1, (0, graphql_1.Args)()),
|
|
77
|
+
__metadata("design:type", Function),
|
|
78
|
+
__metadata("design:paramtypes", [core_1.RequestContext, Object]),
|
|
79
|
+
__metadata("design:returntype", Promise)
|
|
80
|
+
], ReplicateAdminResolver.prototype, "getPredictionItem", null);
|
|
81
|
+
exports.ReplicateAdminResolver = ReplicateAdminResolver = __decorate([
|
|
82
|
+
(0, graphql_1.Resolver)(),
|
|
83
|
+
__metadata("design:paramtypes", [replicate_service_js_1.ReplicateService])
|
|
84
|
+
], ReplicateAdminResolver);
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { OnModuleInit } from "@nestjs/common";
|
|
2
|
+
import { ReplicatePluginOptions, ModelTrainingQueueType, OrderExportQueueType } from "../types.js";
|
|
3
|
+
import { Job, JobQueueService, RequestContext, OrderService, PaginatedList, CustomerService, TransactionalConnection, ID, Customer, ListQueryBuilder, ListQueryOptions } from "@deenruv/core";
|
|
4
|
+
import { StartOrderExportToReplicateInput } from "../graphql/generated-admin-types.js";
|
|
5
|
+
import { ReplicateEntity } from "../entites/replicate.entity.js";
|
|
6
|
+
import { PredictionStatus } from "../zeus/index.js";
|
|
7
|
+
export declare class ReplicateService implements OnModuleInit {
|
|
8
|
+
private readonly options;
|
|
9
|
+
private readonly connection;
|
|
10
|
+
private readonly jobQueueService;
|
|
11
|
+
private readonly orderService;
|
|
12
|
+
private readonly customerService;
|
|
13
|
+
private readonly listQueryBuilder;
|
|
14
|
+
private modelTrainingQueue;
|
|
15
|
+
private orderExportQueue;
|
|
16
|
+
constructor(options: ReplicatePluginOptions, connection: TransactionalConnection, jobQueueService: JobQueueService, orderService: OrderService, customerService: CustomerService, listQueryBuilder: ListQueryBuilder);
|
|
17
|
+
processModelTrainingJob(job: Job<ModelTrainingQueueType>): Promise<void>;
|
|
18
|
+
processOrderExportJob(job: Job<OrderExportQueueType>): Promise<void>;
|
|
19
|
+
modelTrainingJob(ctx: RequestContext, input: any): Promise<void>;
|
|
20
|
+
getPredictionID(ctx: RequestContext, prediction_id: string): Promise<string | undefined>;
|
|
21
|
+
orderExportJob(ctx: RequestContext, input: StartOrderExportToReplicateInput): Promise<ID>;
|
|
22
|
+
onModuleInit(): Promise<void>;
|
|
23
|
+
startModelTraining(ctx: RequestContext, input: any): Promise<void>;
|
|
24
|
+
startOrderExportJob(ctx: RequestContext, input: StartOrderExportToReplicateInput & {
|
|
25
|
+
replicateEntityID: ID;
|
|
26
|
+
}): Promise<void>;
|
|
27
|
+
private randomDate;
|
|
28
|
+
private saveOrdersToCsv;
|
|
29
|
+
private triggerPredictApi;
|
|
30
|
+
checkAndUpdatePredictionStatus(ctx: RequestContext, prediction_id: string): Promise<{
|
|
31
|
+
predictions: never[];
|
|
32
|
+
status: PredictionStatus;
|
|
33
|
+
} | undefined>;
|
|
34
|
+
getPredictionItems(ctx: RequestContext, options?: ListQueryOptions<ReplicateEntity>): Promise<PaginatedList<ReplicateEntity>>;
|
|
35
|
+
getPredictionItem(ctx: RequestContext, id: string): Promise<{
|
|
36
|
+
status: string;
|
|
37
|
+
predictions: {
|
|
38
|
+
id: ID;
|
|
39
|
+
score: number;
|
|
40
|
+
customer: Customer | null;
|
|
41
|
+
}[];
|
|
42
|
+
}>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
3
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
4
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
5
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
6
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
7
|
+
};
|
|
8
|
+
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
9
|
+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
10
|
+
};
|
|
11
|
+
var __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
15
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
16
|
+
};
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.ReplicateService = void 0;
|
|
19
|
+
const common_1 = require("@nestjs/common");
|
|
20
|
+
const constants_js_1 = require("../constants.js");
|
|
21
|
+
const core_1 = require("@deenruv/core");
|
|
22
|
+
const fs_1 = __importDefault(require("fs"));
|
|
23
|
+
const path_1 = __importDefault(require("path"));
|
|
24
|
+
const axios_1 = __importDefault(require("axios"));
|
|
25
|
+
const generated_admin_types_js_1 = require("../graphql/generated-admin-types.js");
|
|
26
|
+
const generated_types_js_1 = require("@deenruv/common/lib/generated-types.js");
|
|
27
|
+
const promises_1 = require("fs/promises");
|
|
28
|
+
const replicate_entity_js_1 = require("../entites/replicate.entity.js");
|
|
29
|
+
const index_js_1 = require("../zeus/index.js");
|
|
30
|
+
const typeorm_1 = require("typeorm");
|
|
31
|
+
let ReplicateService = class ReplicateService {
|
|
32
|
+
constructor(options, connection, jobQueueService, orderService, customerService, listQueryBuilder) {
|
|
33
|
+
this.options = options;
|
|
34
|
+
this.connection = connection;
|
|
35
|
+
this.jobQueueService = jobQueueService;
|
|
36
|
+
this.orderService = orderService;
|
|
37
|
+
this.customerService = customerService;
|
|
38
|
+
this.listQueryBuilder = listQueryBuilder;
|
|
39
|
+
}
|
|
40
|
+
async processModelTrainingJob(job) {
|
|
41
|
+
core_1.Logger.info("initializing model training", constants_js_1.LOGGER_CTX);
|
|
42
|
+
const { serializedContext, startDate, endDate } = job.data;
|
|
43
|
+
const ctx = core_1.RequestContext.deserialize(serializedContext);
|
|
44
|
+
await this.startModelTraining(ctx, { startDate, endDate });
|
|
45
|
+
this.jobQueueService.start();
|
|
46
|
+
}
|
|
47
|
+
async processOrderExportJob(job) {
|
|
48
|
+
core_1.Logger.info("initializing order export", constants_js_1.LOGGER_CTX);
|
|
49
|
+
const { replicateEntityID, serializedContext, startDate, endDate, showMetrics, } = job.data;
|
|
50
|
+
const ctx = core_1.RequestContext.deserialize(serializedContext);
|
|
51
|
+
await this.startOrderExportJob(ctx, {
|
|
52
|
+
replicateEntityID,
|
|
53
|
+
startDate,
|
|
54
|
+
endDate,
|
|
55
|
+
showMetrics,
|
|
56
|
+
});
|
|
57
|
+
this.jobQueueService.start();
|
|
58
|
+
}
|
|
59
|
+
async modelTrainingJob(ctx, input) {
|
|
60
|
+
var _a, _b, _c;
|
|
61
|
+
const serializedContext = ctx.serialize();
|
|
62
|
+
await this.modelTrainingQueue.add({
|
|
63
|
+
serializedContext,
|
|
64
|
+
numLastOrder: (_a = input.numLastOrder) !== null && _a !== void 0 ? _a : 30000,
|
|
65
|
+
startDate: (_b = input.startDate) !== null && _b !== void 0 ? _b : "",
|
|
66
|
+
endDate: (_c = input.endDate) !== null && _c !== void 0 ? _c : "",
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
async getPredictionID(ctx, prediction_id) {
|
|
70
|
+
const entity = await this.connection
|
|
71
|
+
.getRepository(ctx, replicate_entity_js_1.ReplicateEntity)
|
|
72
|
+
.findOne({
|
|
73
|
+
where: { id: prediction_id },
|
|
74
|
+
});
|
|
75
|
+
return entity === null || entity === void 0 ? void 0 : entity.prediction_id;
|
|
76
|
+
}
|
|
77
|
+
async orderExportJob(ctx, input) {
|
|
78
|
+
var _a, _b, _c, _d;
|
|
79
|
+
const entity = await this.connection
|
|
80
|
+
.getRepository(ctx, replicate_entity_js_1.ReplicateEntity)
|
|
81
|
+
.save({});
|
|
82
|
+
const serializedContext = ctx.serialize();
|
|
83
|
+
await this.orderExportQueue.add({
|
|
84
|
+
replicateEntityID: entity.id,
|
|
85
|
+
serializedContext,
|
|
86
|
+
startDate: (_a = input.startDate) !== null && _a !== void 0 ? _a : "",
|
|
87
|
+
endDate: (_b = input.endDate) !== null && _b !== void 0 ? _b : "",
|
|
88
|
+
predictType: (_c = input.predictType) !== null && _c !== void 0 ? _c : generated_admin_types_js_1.PredictionType.RFM_SCORE,
|
|
89
|
+
showMetrics: (_d = input.showMetrics) !== null && _d !== void 0 ? _d : false,
|
|
90
|
+
});
|
|
91
|
+
return entity.id;
|
|
92
|
+
}
|
|
93
|
+
async onModuleInit() {
|
|
94
|
+
this.modelTrainingQueue = await this.jobQueueService.createQueue({
|
|
95
|
+
name: "train-model",
|
|
96
|
+
process: (job) => {
|
|
97
|
+
return this.processModelTrainingJob(job);
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
this.orderExportQueue = await this.jobQueueService.createQueue({
|
|
101
|
+
name: "order-export",
|
|
102
|
+
process: (job) => {
|
|
103
|
+
return this.processOrderExportJob(job);
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
async startModelTraining(ctx, input) {
|
|
108
|
+
try {
|
|
109
|
+
const { numLastOrder } = input;
|
|
110
|
+
const customerService = this.customerService;
|
|
111
|
+
const orderService = this.orderService;
|
|
112
|
+
for (let i = 0; i < (numLastOrder !== null && numLastOrder !== void 0 ? numLastOrder : 30000); i++) {
|
|
113
|
+
const uniqueEmail = `test${i}_${Date.now()}@example.com`;
|
|
114
|
+
const customer = await customerService.create(ctx, {
|
|
115
|
+
emailAddress: uniqueEmail,
|
|
116
|
+
firstName: "test",
|
|
117
|
+
lastName: "replicatetest",
|
|
118
|
+
phoneNumber: "123456789",
|
|
119
|
+
title: "Mr",
|
|
120
|
+
});
|
|
121
|
+
if ("errorCode" in customer) {
|
|
122
|
+
core_1.Logger.error(`Failed to create customer: ${customer.errorCode}`, constants_js_1.LOGGER_CTX);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const randomNumber = Math.floor(Math.random() * 7) + 1;
|
|
126
|
+
for (let j = 0; j < randomNumber; j++) {
|
|
127
|
+
const order = await orderService.addCustomerToOrder(ctx, await orderService.create(ctx, 1), customer);
|
|
128
|
+
const itemsToAdd = Math.floor(Math.random() * 5) + 1;
|
|
129
|
+
await orderService.addItemToOrder(ctx, order.id, 1, itemsToAdd);
|
|
130
|
+
await orderService.transitionToState(ctx, order.id, "AddingItems");
|
|
131
|
+
await orderService.setShippingAddress(ctx, order.id, {
|
|
132
|
+
streetLine1: "test",
|
|
133
|
+
countryCode: "PL",
|
|
134
|
+
});
|
|
135
|
+
await orderService.setShippingMethod(ctx, order.id, [1, 2]);
|
|
136
|
+
await orderService.transitionToState(ctx, order.id, "ArrangingPayment");
|
|
137
|
+
await orderService.addPaymentToOrder(ctx, order.id, {
|
|
138
|
+
method: "standard-payment",
|
|
139
|
+
metadata: {
|
|
140
|
+
transfer_group: "",
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
await orderService.transitionToState(ctx, order.id, "PaymentAuthorized");
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
core_1.Logger.error("model training failed", constants_js_1.LOGGER_CTX);
|
|
149
|
+
console.error("Error:", error);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
async startOrderExportJob(ctx, input) {
|
|
153
|
+
const { showMetrics, replicateEntityID } = input;
|
|
154
|
+
let { startDate, endDate, predictType } = input;
|
|
155
|
+
startDate = startDate || null;
|
|
156
|
+
endDate = endDate || null;
|
|
157
|
+
predictType = predictType !== null && predictType !== void 0 ? predictType : generated_admin_types_js_1.PredictionType.RFM_SCORE;
|
|
158
|
+
core_1.Logger.info("starting order export", constants_js_1.LOGGER_CTX);
|
|
159
|
+
const columnNames = [
|
|
160
|
+
"InvoiceNo",
|
|
161
|
+
"InvoiceDate",
|
|
162
|
+
"Total",
|
|
163
|
+
"CustomerId",
|
|
164
|
+
"Products",
|
|
165
|
+
];
|
|
166
|
+
const csv = [columnNames.join(",")];
|
|
167
|
+
const LatestOrders = await this.orderService.findAll(ctx, {
|
|
168
|
+
filter: {
|
|
169
|
+
orderPlacedAt: startDate && endDate
|
|
170
|
+
? {
|
|
171
|
+
between: {
|
|
172
|
+
start: new Date(startDate),
|
|
173
|
+
end: new Date(endDate),
|
|
174
|
+
},
|
|
175
|
+
}
|
|
176
|
+
: { isNull: false },
|
|
177
|
+
},
|
|
178
|
+
});
|
|
179
|
+
const numLatestOrders = LatestOrders.totalItems;
|
|
180
|
+
let batch = 1;
|
|
181
|
+
if (numLatestOrders > 1000) {
|
|
182
|
+
batch = Math.ceil(numLatestOrders / 1000);
|
|
183
|
+
}
|
|
184
|
+
for (let i = 0; i < batch; i++) {
|
|
185
|
+
const orders = await this.orderService.findAll(ctx, {
|
|
186
|
+
skip: i * 1000,
|
|
187
|
+
take: 1000,
|
|
188
|
+
filter: {
|
|
189
|
+
orderPlacedAt: startDate && endDate
|
|
190
|
+
? {
|
|
191
|
+
between: {
|
|
192
|
+
start: new Date(startDate),
|
|
193
|
+
end: new Date(endDate),
|
|
194
|
+
},
|
|
195
|
+
}
|
|
196
|
+
: { isNull: false },
|
|
197
|
+
},
|
|
198
|
+
sort: {
|
|
199
|
+
orderPlacedAt: generated_types_js_1.SortOrder.DESC,
|
|
200
|
+
},
|
|
201
|
+
});
|
|
202
|
+
if (!orders.items.length)
|
|
203
|
+
break;
|
|
204
|
+
await this.saveOrdersToCsv(csv, orders);
|
|
205
|
+
}
|
|
206
|
+
const csvString = csv.join("\n");
|
|
207
|
+
const tmp = await (0, promises_1.mkdtemp)("orders");
|
|
208
|
+
const filePath = path_1.default.join(tmp, "./orders.csv");
|
|
209
|
+
fs_1.default.writeFileSync(filePath, csvString);
|
|
210
|
+
core_1.Logger.info("order export completed", constants_js_1.LOGGER_CTX);
|
|
211
|
+
const result = await this.triggerPredictApi(filePath, predictType, showMetrics || false);
|
|
212
|
+
if (!result) {
|
|
213
|
+
throw new Error("Failed to trigger predict API");
|
|
214
|
+
}
|
|
215
|
+
const { prediction_id, status } = result;
|
|
216
|
+
await this.connection
|
|
217
|
+
.getRepository(ctx, replicate_entity_js_1.ReplicateEntity)
|
|
218
|
+
.update({ id: replicateEntityID, status: status }, { prediction_id, status });
|
|
219
|
+
await (0, promises_1.rm)(tmp, { recursive: true, force: true });
|
|
220
|
+
}
|
|
221
|
+
async randomDate(start, end, startHour, endHour) {
|
|
222
|
+
const date = new Date(start.getTime() + Math.random() * (end.getTime() - start.getTime()));
|
|
223
|
+
const hour = (startHour + Math.random() * (endHour - startHour)) | 0;
|
|
224
|
+
date.setHours(hour);
|
|
225
|
+
return date;
|
|
226
|
+
}
|
|
227
|
+
async saveOrdersToCsv(csv, orders) {
|
|
228
|
+
const orderData = await Promise.all(orders.items.map(async (order) => {
|
|
229
|
+
var _a;
|
|
230
|
+
return [
|
|
231
|
+
order.id,
|
|
232
|
+
((_a = order.orderPlacedAt) !== null && _a !== void 0 ? _a : (await this.randomDate(new Date(2024, 1, 1), new Date(2025, 1, 1), 0, 23))).toISOString(),
|
|
233
|
+
order.totalWithTax,
|
|
234
|
+
order.customerId,
|
|
235
|
+
"ALL",
|
|
236
|
+
].join(",");
|
|
237
|
+
}));
|
|
238
|
+
csv.push(...orderData);
|
|
239
|
+
}
|
|
240
|
+
async triggerPredictApi(filePath, predictType, showMetrics) {
|
|
241
|
+
try {
|
|
242
|
+
const fileData = await fs_1.default.promises.readFile(filePath);
|
|
243
|
+
const base64Data = fileData.toString("base64");
|
|
244
|
+
const fileInput = `data:text/csv;base64,${base64Data}`;
|
|
245
|
+
let replicatePredictType = "";
|
|
246
|
+
if (predictType === generated_admin_types_js_1.PredictionType.RFM_SCORE)
|
|
247
|
+
replicatePredictType = "rfm-score";
|
|
248
|
+
if (predictType === generated_admin_types_js_1.PredictionType.SEGMENTATION)
|
|
249
|
+
replicatePredictType = "segmentation";
|
|
250
|
+
if (!this.options.deploymentName === undefined) {
|
|
251
|
+
throw new Error("Replicate: deployment name token not set");
|
|
252
|
+
}
|
|
253
|
+
if (!this.options.apiToken === undefined) {
|
|
254
|
+
throw new Error("Replicate: API token not set");
|
|
255
|
+
}
|
|
256
|
+
const response = await axios_1.default.post(`https://api.replicate.com/v1/deployments/aexol-studio/${this.options.deploymentName}/predictions`, {
|
|
257
|
+
input: {
|
|
258
|
+
data_path: fileInput,
|
|
259
|
+
predict_type: replicatePredictType,
|
|
260
|
+
show_metrics: showMetrics,
|
|
261
|
+
},
|
|
262
|
+
}, {
|
|
263
|
+
headers: {
|
|
264
|
+
Authorization: `Bearer ${this.options.apiToken}`,
|
|
265
|
+
"Content-Type": `application/json`,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
return { prediction_id: response.data.id, status: response.data.status };
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
core_1.Logger.error("API call to replicate failed", constants_js_1.LOGGER_CTX);
|
|
272
|
+
console.error("Error:", error);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async checkAndUpdatePredictionStatus(ctx, prediction_id) {
|
|
276
|
+
var _a, _b;
|
|
277
|
+
try {
|
|
278
|
+
const response = await axios_1.default.get(`https://api.replicate.com/v1/predictions/${prediction_id}`, {
|
|
279
|
+
headers: {
|
|
280
|
+
Authorization: `Bearer ${this.options.apiToken}`,
|
|
281
|
+
"Content-Type": "application/json",
|
|
282
|
+
},
|
|
283
|
+
});
|
|
284
|
+
const status = response.data.status;
|
|
285
|
+
let outputDict = {};
|
|
286
|
+
if ((_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.error) {
|
|
287
|
+
await this.connection.getRepository(ctx, replicate_entity_js_1.ReplicateEntity).update({ prediction_id }, {
|
|
288
|
+
status: index_js_1.PredictionStatus.failed,
|
|
289
|
+
finishedAt: response.data.completed_at,
|
|
290
|
+
});
|
|
291
|
+
return { predictions: [], status: index_js_1.PredictionStatus.failed };
|
|
292
|
+
}
|
|
293
|
+
try {
|
|
294
|
+
outputDict = JSON.parse(((_b = response === null || response === void 0 ? void 0 : response.data) === null || _b === void 0 ? void 0 : _b.output) || "{}");
|
|
295
|
+
}
|
|
296
|
+
catch (error) {
|
|
297
|
+
core_1.Logger.error("Failed to parse output", constants_js_1.LOGGER_CTX);
|
|
298
|
+
}
|
|
299
|
+
const data = [];
|
|
300
|
+
for (const key in outputDict) {
|
|
301
|
+
data.push([key, outputDict[key]]);
|
|
302
|
+
}
|
|
303
|
+
data.sort(([_1, ascore], [_2, bscore]) => bscore - ascore);
|
|
304
|
+
const predictions = [];
|
|
305
|
+
for (let i = 0; i < data.length; i += 100) {
|
|
306
|
+
const view = data.slice(i, Math.max(i + 100, data.length));
|
|
307
|
+
const res = await this.connection.getRepository(ctx, core_1.Customer).find({
|
|
308
|
+
where: {
|
|
309
|
+
id: (0, typeorm_1.In)(view.map(([id]) => parseInt(id))),
|
|
310
|
+
},
|
|
311
|
+
});
|
|
312
|
+
predictions.push(...view
|
|
313
|
+
.map(([id, score]) => {
|
|
314
|
+
const customer = res.find((r) => +r.id === +id);
|
|
315
|
+
if (!(customer === null || customer === void 0 ? void 0 : customer.emailAddress)) {
|
|
316
|
+
return null;
|
|
317
|
+
}
|
|
318
|
+
return {
|
|
319
|
+
id,
|
|
320
|
+
score,
|
|
321
|
+
customer: res.find((r) => +r.id === +id),
|
|
322
|
+
};
|
|
323
|
+
})
|
|
324
|
+
.filter((x) => !!x));
|
|
325
|
+
}
|
|
326
|
+
const output = predictions.map(({ customer, score }) => ({
|
|
327
|
+
customerId: customer === null || customer === void 0 ? void 0 : customer.id,
|
|
328
|
+
score,
|
|
329
|
+
customer,
|
|
330
|
+
}));
|
|
331
|
+
if (status !== "starting" && response.data.output) {
|
|
332
|
+
await this.connection.getRepository(ctx, replicate_entity_js_1.ReplicateEntity).update({ prediction_id }, {
|
|
333
|
+
output: output,
|
|
334
|
+
status: status,
|
|
335
|
+
finishedAt: response.data.completed_at,
|
|
336
|
+
});
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
catch (error) {
|
|
340
|
+
core_1.Logger.error("API call to check and update prediction status failed", constants_js_1.LOGGER_CTX);
|
|
341
|
+
console.error("Error:", error);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
async getPredictionItems(ctx, options) {
|
|
345
|
+
const qb = this.listQueryBuilder.build(replicate_entity_js_1.ReplicateEntity, options, { ctx });
|
|
346
|
+
const [items, totalItems] = await qb.getManyAndCount();
|
|
347
|
+
return { items, totalItems };
|
|
348
|
+
}
|
|
349
|
+
async getPredictionItem(ctx, id) {
|
|
350
|
+
const prediction = await this.connection
|
|
351
|
+
.getRepository(ctx, replicate_entity_js_1.ReplicateEntity)
|
|
352
|
+
.findOne({ where: { id } });
|
|
353
|
+
if (!prediction) {
|
|
354
|
+
throw new Error("Prediction not found");
|
|
355
|
+
}
|
|
356
|
+
if (prediction.status === index_js_1.PredictionStatus.starting) {
|
|
357
|
+
await this.checkAndUpdatePredictionStatus(ctx, prediction.prediction_id.toString());
|
|
358
|
+
}
|
|
359
|
+
if (prediction.output) {
|
|
360
|
+
const output = await Promise.all(prediction.output.map(async ({ customerId, score }) => {
|
|
361
|
+
const customer = await this.connection
|
|
362
|
+
.getRepository(ctx, core_1.Customer)
|
|
363
|
+
.findOne({ where: { id: customerId } });
|
|
364
|
+
return {
|
|
365
|
+
id: customerId,
|
|
366
|
+
score,
|
|
367
|
+
customer,
|
|
368
|
+
};
|
|
369
|
+
}));
|
|
370
|
+
return { status: prediction.status, predictions: output };
|
|
371
|
+
}
|
|
372
|
+
return { status: prediction.status, predictions: [] };
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
exports.ReplicateService = ReplicateService;
|
|
376
|
+
exports.ReplicateService = ReplicateService = __decorate([
|
|
377
|
+
(0, common_1.Injectable)(),
|
|
378
|
+
__param(0, (0, common_1.Inject)(constants_js_1.REPLICATE_PLUGIN_OPTIONS)),
|
|
379
|
+
__param(1, (0, common_1.Inject)(core_1.TransactionalConnection)),
|
|
380
|
+
__param(2, (0, common_1.Inject)(core_1.JobQueueService)),
|
|
381
|
+
__param(3, (0, common_1.Inject)(core_1.OrderService)),
|
|
382
|
+
__param(4, (0, common_1.Inject)(core_1.CustomerService)),
|
|
383
|
+
__param(5, (0, common_1.Inject)(core_1.ListQueryBuilder)),
|
|
384
|
+
__metadata("design:paramtypes", [Object, core_1.TransactionalConnection,
|
|
385
|
+
core_1.JobQueueService,
|
|
386
|
+
core_1.OrderService,
|
|
387
|
+
core_1.CustomerService,
|
|
388
|
+
core_1.ListQueryBuilder])
|
|
389
|
+
], ReplicateService);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { ID, SerializedRequestContext } from "@deenruv/core";
|
|
2
|
+
export interface ReplicatePluginOptions {
|
|
3
|
+
deploymentName: string;
|
|
4
|
+
apiToken: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ModelTrainingQueueType {
|
|
7
|
+
serializedContext: SerializedRequestContext;
|
|
8
|
+
numLastOrder: number;
|
|
9
|
+
startDate: string;
|
|
10
|
+
endDate: string;
|
|
11
|
+
}
|
|
12
|
+
export interface OrderExportQueueType {
|
|
13
|
+
serializedContext: SerializedRequestContext;
|
|
14
|
+
startDate: string;
|
|
15
|
+
endDate: string;
|
|
16
|
+
predictType: string;
|
|
17
|
+
showMetrics: boolean;
|
|
18
|
+
replicateEntityID: ID;
|
|
19
|
+
}
|