@vendure/dashboard 3.3.8 → 3.4.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/README.md +62 -0
- package/dist/plugin/api/api-extensions.d.ts +1 -0
- package/dist/plugin/api/api-extensions.js +38 -0
- package/dist/plugin/api/metrics.resolver.d.ts +8 -0
- package/dist/plugin/api/metrics.resolver.js +40 -0
- package/dist/plugin/config/metrics-strategies.d.ts +39 -0
- package/dist/plugin/config/metrics-strategies.js +74 -0
- package/dist/plugin/constants.d.ts +4 -3
- package/dist/plugin/constants.js +10 -277
- package/dist/plugin/dashboard.plugin.d.ts +95 -0
- package/dist/plugin/dashboard.plugin.js +168 -0
- package/dist/plugin/index.d.ts +2 -1
- package/dist/plugin/index.js +18 -1
- package/dist/plugin/package.json +3 -0
- package/dist/plugin/service/metrics.service.d.ts +15 -0
- package/dist/plugin/service/metrics.service.js +145 -0
- package/dist/plugin/types.d.ts +20 -37
- package/dist/plugin/types.js +13 -1
- package/dist/vite/constants.d.ts +5 -0
- package/dist/vite/constants.js +277 -0
- package/dist/vite/index.d.ts +1 -0
- package/dist/vite/index.js +1 -0
- package/dist/vite/types.d.ts +40 -0
- package/dist/vite/utils/config-loader.js +1 -0
- package/dist/{plugin → vite}/utils/plugin-discovery.js +1 -1
- package/dist/vite/utils/ui-config.d.ts +3 -0
- package/dist/vite/utils/ui-config.js +30 -0
- package/dist/vite/vite-plugin-ui-config.d.ts +123 -0
- package/dist/{plugin → vite}/vite-plugin-ui-config.js +3 -11
- package/dist/{plugin → vite}/vite-plugin-vendure-dashboard.js +1 -1
- package/index.html +1 -1
- package/package.json +16 -7
- package/src/app/app-providers.tsx +1 -1
- package/src/app/routes/_authenticated/_collections/collections_.$id.tsx +1 -1
- package/src/app/routes/_authenticated/_facets/components/facet-values-table.tsx +20 -35
- package/src/app/routes/_authenticated/_facets/facets.graphql.ts +40 -0
- package/src/app/routes/_authenticated/_facets/facets_.$facetId.values_.$id.tsx +147 -0
- package/src/app/routes/_authenticated/_orders/components/order-history/order-history.tsx +380 -33
- package/src/app/routes/_authenticated/_products/components/option-value-input.tsx +1 -1
- package/src/app/routes/_authenticated/_system/healthchecks.tsx +1 -1
- package/src/app/routes/_authenticated/_system/job-queue.tsx +1 -0
- package/src/app/routes/_authenticated/index.tsx +2 -2
- package/src/app/routes/_authenticated.tsx +1 -1
- package/src/lib/components/data-input/rich-text-input.tsx +14 -8
- package/src/lib/components/data-table/data-table-bulk-actions.tsx +17 -4
- package/src/lib/components/layout/app-layout.tsx +2 -7
- package/src/lib/components/layout/channel-switcher.tsx +166 -57
- package/src/lib/components/layout/dev-mode-indicator.tsx +18 -0
- package/src/lib/components/layout/language-dialog.tsx +2 -1
- package/src/lib/components/layout/manage-languages-dialog.tsx +77 -40
- package/src/lib/components/layout/nav-item-wrapper.tsx +107 -0
- package/src/lib/components/layout/nav-main.tsx +196 -107
- package/src/lib/components/login/login-form.tsx +80 -45
- package/src/lib/components/shared/asset/asset-bulk-actions.tsx +19 -4
- package/src/lib/components/shared/asset/asset-gallery.tsx +2 -2
- package/src/lib/components/shared/detail-page-button.tsx +42 -0
- package/src/lib/components/shared/history-timeline/history-entry-date.tsx +37 -0
- package/src/lib/components/shared/history-timeline/history-entry.tsx +135 -65
- package/src/lib/components/shared/history-timeline/history-note-input.tsx +4 -4
- package/src/lib/components/shared/history-timeline/history-timeline.tsx +7 -54
- package/src/lib/components/shared/translatable-form-field.tsx +16 -2
- package/src/lib/framework/defaults.ts +4 -10
- package/src/lib/framework/extension-api/define-dashboard-extension.ts +4 -0
- package/src/lib/framework/extension-api/extension-api-types.ts +11 -2
- package/src/lib/framework/extension-api/logic/index.ts +1 -0
- package/src/lib/framework/extension-api/logic/login.ts +17 -0
- package/src/lib/framework/extension-api/logic/navigation.ts +1 -0
- package/src/lib/framework/extension-api/types/data-table.ts +12 -3
- package/src/lib/framework/extension-api/types/detail-forms.ts +13 -0
- package/src/lib/framework/extension-api/types/form-components.ts +11 -0
- package/src/lib/framework/extension-api/types/index.ts +1 -0
- package/src/lib/framework/extension-api/types/layout.ts +3 -6
- package/src/lib/framework/extension-api/types/login.ts +96 -0
- package/src/lib/framework/extension-api/types/navigation.ts +57 -0
- package/src/lib/framework/extension-api/types/widgets.ts +0 -4
- package/src/lib/framework/extension-api/use-login-extensions.ts +26 -0
- package/src/lib/framework/layout-engine/dev-mode-button.tsx +24 -0
- package/src/lib/framework/layout-engine/location-wrapper.tsx +5 -12
- package/src/lib/framework/registry/global-registry.ts +4 -0
- package/src/lib/framework/registry/registry-types.ts +2 -0
- package/src/lib/graphql/api.ts +25 -3
- package/src/lib/graphql/graphql-env.d.ts +28 -28
- package/src/lib/graphql/settings-store-operations.ts +17 -0
- package/src/lib/hooks/use-floating-bulk-actions.ts +82 -0
- package/src/lib/hooks/use-local-format.ts +20 -5
- package/src/lib/index.ts +2 -1
- package/src/lib/providers/channel-provider.tsx +13 -11
- package/src/lib/providers/user-settings.tsx +78 -3
- package/src/lib/virtual.d.ts +26 -2
- package/src/vite-env.d.ts +2 -0
- package/vite/utils/plugin-discovery.ts +1 -1
- package/vite/utils/ui-config.ts +30 -42
- package/vite/vite-plugin-ui-config.ts +119 -17
- package/vite/vite-plugin-vendure-dashboard.ts +1 -1
- package/dist/plugin/utils/ui-config.d.ts +0 -3
- package/dist/plugin/utils/ui-config.js +0 -34
- package/dist/plugin/vite-plugin-ui-config.d.ts +0 -15
- package/src/app/routes/_authenticated/_facets/components/add-facet-value-dialog.tsx +0 -146
- package/src/lib/components/shared/rich-text-editor.tsx +0 -0
- /package/dist/{plugin/utils/ast-utils.spec.d.ts → vite/types.js} +0 -0
- /package/dist/{plugin → vite}/utils/ast-utils.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/ast-utils.js +0 -0
- /package/dist/{plugin/utils/config-loader.d.ts → vite/utils/ast-utils.spec.d.ts} +0 -0
- /package/dist/{plugin → vite}/utils/ast-utils.spec.js +0 -0
- /package/dist/{plugin → vite}/utils/compiler.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/compiler.js +0 -0
- /package/dist/{plugin/utils/config-loader.js → vite/utils/config-loader.d.ts} +0 -0
- /package/dist/{plugin → vite}/utils/logger.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/logger.js +0 -0
- /package/dist/{plugin → vite}/utils/plugin-discovery.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/schema-generator.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/schema-generator.js +0 -0
- /package/dist/{plugin → vite}/utils/tsconfig-utils.d.ts +0 -0
- /package/dist/{plugin → vite}/utils/tsconfig-utils.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-admin-api-schema.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-admin-api-schema.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config-loader.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config-loader.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-config.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-dashboard-metadata.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-dashboard-metadata.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-gql-tada.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-gql-tada.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-tailwind-source.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-tailwind-source.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-theme.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-theme.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-transform-index.d.ts +0 -0
- /package/dist/{plugin → vite}/vite-plugin-transform-index.js +0 -0
- /package/dist/{plugin → vite}/vite-plugin-vendure-dashboard.d.ts +0 -0
|
@@ -0,0 +1,168 @@
|
|
|
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 __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
var DashboardPlugin_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.DashboardPlugin = void 0;
|
|
17
|
+
const core_1 = require("@vendure/core");
|
|
18
|
+
const express_1 = __importDefault(require("express"));
|
|
19
|
+
const express_rate_limit_1 = require("express-rate-limit");
|
|
20
|
+
const fs_extra_1 = __importDefault(require("fs-extra"));
|
|
21
|
+
const path_1 = __importDefault(require("path"));
|
|
22
|
+
const api_extensions_js_1 = require("./api/api-extensions.js");
|
|
23
|
+
const metrics_resolver_js_1 = require("./api/metrics.resolver.js");
|
|
24
|
+
const constants_js_1 = require("./constants.js");
|
|
25
|
+
const metrics_service_js_1 = require("./service/metrics.service.js");
|
|
26
|
+
/**
|
|
27
|
+
* @description
|
|
28
|
+
* This plugin serves the static files of the Vendure Dashboard and provides the
|
|
29
|
+
* GraphQL extensions needed for the order metrics on the dashboard index page.
|
|
30
|
+
*
|
|
31
|
+
* ## Installation
|
|
32
|
+
*
|
|
33
|
+
* `npm install \@vendure/dashboard`
|
|
34
|
+
*
|
|
35
|
+
* ## Usage
|
|
36
|
+
*
|
|
37
|
+
* First you need to set up compilation of the Dashboard, using the Vite configuration
|
|
38
|
+
* described in the [Dashboard Getting Started Guide](/guides/extending-the-dashboard/getting-started/)
|
|
39
|
+
*
|
|
40
|
+
* Once set up, you run `npx vite build` to build the production version of the dashboard app.
|
|
41
|
+
*
|
|
42
|
+
* The built app files will be output to the location specified by `build.outDir` in your Vite
|
|
43
|
+
* config file. This should then be passed to the `appDir` init option, as in the example below:
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* ```ts
|
|
47
|
+
* import { DashboardPlugin } from '\@vendure/dashboard/plugin';
|
|
48
|
+
*
|
|
49
|
+
* const config: VendureConfig = {
|
|
50
|
+
* // Add an instance of the plugin to the plugins array
|
|
51
|
+
* plugins: [
|
|
52
|
+
* DashboardPlugin.init({
|
|
53
|
+
* route: 'dashboard',
|
|
54
|
+
* appDir: './dist/dashboard',
|
|
55
|
+
* }),
|
|
56
|
+
* ],
|
|
57
|
+
* };
|
|
58
|
+
* ```
|
|
59
|
+
*
|
|
60
|
+
* ## Metrics
|
|
61
|
+
*
|
|
62
|
+
* This plugin defines a `metricSummary` query which is used by the Dashboard UI to
|
|
63
|
+
* display the order metrics on the dashboard.
|
|
64
|
+
*
|
|
65
|
+
* If you are building a stand-alone version of the Dashboard UI app, and therefore
|
|
66
|
+
* don't need this plugin to serve the Dashboard UI, you can still use the
|
|
67
|
+
* `metricSummary` query by adding the `DashboardPlugin` to the `plugins` array,
|
|
68
|
+
* but without calling the `init()` method:
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* ```ts
|
|
72
|
+
* import { DashboardPlugin } from '\@vendure/dashboard-plugin';
|
|
73
|
+
*
|
|
74
|
+
* const config: VendureConfig = {
|
|
75
|
+
* plugins: [
|
|
76
|
+
* DashboardPlugin, // <-- no call to .init()
|
|
77
|
+
* ],
|
|
78
|
+
* // ...
|
|
79
|
+
* };
|
|
80
|
+
* ```
|
|
81
|
+
*
|
|
82
|
+
* @docsCategory core plugins/DashboardPlugin
|
|
83
|
+
*/
|
|
84
|
+
let DashboardPlugin = DashboardPlugin_1 = class DashboardPlugin {
|
|
85
|
+
constructor(processContext) {
|
|
86
|
+
this.processContext = processContext;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* @description
|
|
90
|
+
* Set the plugin options
|
|
91
|
+
*/
|
|
92
|
+
static init(options) {
|
|
93
|
+
this.options = options;
|
|
94
|
+
return DashboardPlugin_1;
|
|
95
|
+
}
|
|
96
|
+
configure(consumer) {
|
|
97
|
+
if (this.processContext.isWorker) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (!DashboardPlugin_1.options) {
|
|
101
|
+
core_1.Logger.info(`DashboardPlugin's init() method was not called. The Dashboard UI will not be served.`, constants_js_1.loggerCtx);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const { route, appDir } = DashboardPlugin_1.options;
|
|
105
|
+
const dashboardPath = appDir || this.getDashboardPath();
|
|
106
|
+
core_1.Logger.info('Creating dashboard middleware', constants_js_1.loggerCtx);
|
|
107
|
+
consumer.apply(this.createStaticServer(dashboardPath)).forRoutes(route);
|
|
108
|
+
(0, core_1.registerPluginStartupMessage)('Dashboard UI', route);
|
|
109
|
+
}
|
|
110
|
+
createStaticServer(dashboardPath) {
|
|
111
|
+
const limiter = (0, express_rate_limit_1.rateLimit)({
|
|
112
|
+
windowMs: 60 * 1000,
|
|
113
|
+
limit: process.env.NODE_ENV === 'production' ? 500 : 2000,
|
|
114
|
+
standardHeaders: true,
|
|
115
|
+
legacyHeaders: false,
|
|
116
|
+
});
|
|
117
|
+
const dashboardServer = express_1.default.Router();
|
|
118
|
+
// This is a workaround for a type mismatch between express v5 (Vendure core)
|
|
119
|
+
// and express v4 (several transitive dependencies). Can be removed once the
|
|
120
|
+
// ecosystem has more significantly shifted to v5.
|
|
121
|
+
dashboardServer.use(limiter);
|
|
122
|
+
dashboardServer.use(express_1.default.static(dashboardPath));
|
|
123
|
+
dashboardServer.use((req, res) => {
|
|
124
|
+
res.sendFile('index.html', { root: dashboardPath });
|
|
125
|
+
});
|
|
126
|
+
return dashboardServer;
|
|
127
|
+
}
|
|
128
|
+
getDashboardPath() {
|
|
129
|
+
// First, try to find the dashboard dist directory in the @vendure/dashboard package
|
|
130
|
+
try {
|
|
131
|
+
const dashboardPackageJson = require.resolve('@vendure/dashboard/package.json');
|
|
132
|
+
const dashboardPackageRoot = path_1.default.dirname(dashboardPackageJson);
|
|
133
|
+
const dashboardDistPath = path_1.default.join(dashboardPackageRoot, 'dist');
|
|
134
|
+
if (fs_extra_1.default.existsSync(dashboardDistPath)) {
|
|
135
|
+
core_1.Logger.info(`Found dashboard UI at ${dashboardDistPath}`, constants_js_1.loggerCtx);
|
|
136
|
+
return dashboardDistPath;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (e) {
|
|
140
|
+
// Dashboard package not found, continue to fallback
|
|
141
|
+
}
|
|
142
|
+
// Fallback to default path
|
|
143
|
+
core_1.Logger.warn(`Could not find @vendure/dashboard dist directory. Falling back to default path: ${constants_js_1.DEFAULT_APP_PATH}`, constants_js_1.loggerCtx);
|
|
144
|
+
return constants_js_1.DEFAULT_APP_PATH;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
exports.DashboardPlugin = DashboardPlugin;
|
|
148
|
+
exports.DashboardPlugin = DashboardPlugin = DashboardPlugin_1 = __decorate([
|
|
149
|
+
(0, core_1.VendurePlugin)({
|
|
150
|
+
imports: [core_1.PluginCommonModule],
|
|
151
|
+
adminApiExtensions: {
|
|
152
|
+
schema: api_extensions_js_1.adminApiExtensions,
|
|
153
|
+
resolvers: [metrics_resolver_js_1.MetricsResolver],
|
|
154
|
+
},
|
|
155
|
+
providers: [metrics_service_js_1.MetricsService],
|
|
156
|
+
configuration: config => {
|
|
157
|
+
config.settingsStoreFields['vendure.dashboard'] = [
|
|
158
|
+
{
|
|
159
|
+
name: 'userSettings',
|
|
160
|
+
scope: core_1.SettingsStoreScopes.user,
|
|
161
|
+
},
|
|
162
|
+
];
|
|
163
|
+
return config;
|
|
164
|
+
},
|
|
165
|
+
compatibility: '^3.0.0',
|
|
166
|
+
}),
|
|
167
|
+
__metadata("design:paramtypes", [core_1.ProcessContext])
|
|
168
|
+
], DashboardPlugin);
|
package/dist/plugin/index.d.ts
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
export
|
|
1
|
+
export * from './dashboard.plugin.js';
|
|
2
|
+
export * from './types.js';
|
package/dist/plugin/index.js
CHANGED
|
@@ -1 +1,18 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./dashboard.plugin.js"), exports);
|
|
18
|
+
__exportStar(require("./types.js"), exports);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { CacheService, Order, RequestContext, TransactionalConnection } from '@vendure/core';
|
|
2
|
+
import { MetricCalculation } from '../config/metrics-strategies.js';
|
|
3
|
+
import { MetricInterval, MetricSummary, MetricSummaryInput } from '../types.js';
|
|
4
|
+
export type MetricData = {
|
|
5
|
+
date: Date;
|
|
6
|
+
orders: Order[];
|
|
7
|
+
};
|
|
8
|
+
export declare class MetricsService {
|
|
9
|
+
private connection;
|
|
10
|
+
private cacheService;
|
|
11
|
+
metricCalculations: MetricCalculation[];
|
|
12
|
+
constructor(connection: TransactionalConnection, cacheService: CacheService);
|
|
13
|
+
getMetrics(ctx: RequestContext, { interval, types, refresh }: MetricSummaryInput): Promise<MetricSummary[]>;
|
|
14
|
+
loadData(ctx: RequestContext, interval: MetricInterval, endDate: Date): Promise<Map<number, MetricData>>;
|
|
15
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.MetricsService = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const shared_utils_1 = require("@vendure/common/lib/shared-utils");
|
|
15
|
+
const core_1 = require("@vendure/core");
|
|
16
|
+
const crypto_1 = require("crypto");
|
|
17
|
+
const date_fns_1 = require("date-fns");
|
|
18
|
+
const metrics_strategies_js_1 = require("../config/metrics-strategies.js");
|
|
19
|
+
const constants_js_1 = require("../constants.js");
|
|
20
|
+
const types_js_1 = require("../types.js");
|
|
21
|
+
let MetricsService = class MetricsService {
|
|
22
|
+
constructor(connection, cacheService) {
|
|
23
|
+
this.connection = connection;
|
|
24
|
+
this.cacheService = cacheService;
|
|
25
|
+
this.metricCalculations = [
|
|
26
|
+
new metrics_strategies_js_1.AverageOrderValueMetric(),
|
|
27
|
+
new metrics_strategies_js_1.OrderCountMetric(),
|
|
28
|
+
new metrics_strategies_js_1.OrderTotalMetric(),
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
async getMetrics(ctx, { interval, types, refresh }) {
|
|
32
|
+
// Set 23:59:59.999 as endDate
|
|
33
|
+
const endDate = (0, date_fns_1.endOfDay)(new Date());
|
|
34
|
+
// Check if we have cached result
|
|
35
|
+
const hash = (0, crypto_1.createHash)('sha1')
|
|
36
|
+
.update(JSON.stringify({
|
|
37
|
+
endDate,
|
|
38
|
+
types: types.sort(),
|
|
39
|
+
interval,
|
|
40
|
+
channel: ctx.channel.token,
|
|
41
|
+
}))
|
|
42
|
+
.digest('base64');
|
|
43
|
+
const cacheKey = `MetricsService:${hash}`;
|
|
44
|
+
const cachedMetricList = await this.cacheService.get(cacheKey);
|
|
45
|
+
if (cachedMetricList && refresh !== true) {
|
|
46
|
+
core_1.Logger.verbose(`Returning cached metrics for channel ${ctx.channel.token}`, constants_js_1.loggerCtx);
|
|
47
|
+
return cachedMetricList;
|
|
48
|
+
}
|
|
49
|
+
// No cache, calculating new metrics
|
|
50
|
+
core_1.Logger.verbose(`No cache hit, calculating ${interval} metrics until ${endDate.toISOString()} for channel ${ctx.channel.token} for all orders`, constants_js_1.loggerCtx);
|
|
51
|
+
const data = await this.loadData(ctx, interval, endDate);
|
|
52
|
+
const metrics = [];
|
|
53
|
+
for (const type of types) {
|
|
54
|
+
const metric = this.metricCalculations.find(m => m.type === type);
|
|
55
|
+
if (!metric) {
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Calculate entry (month or week)
|
|
59
|
+
const entries = [];
|
|
60
|
+
data.forEach(dataPerTick => {
|
|
61
|
+
entries.push(metric.calculateEntry(ctx, interval, dataPerTick));
|
|
62
|
+
});
|
|
63
|
+
// Create metric with calculated entries
|
|
64
|
+
metrics.push({
|
|
65
|
+
interval,
|
|
66
|
+
title: metric.getTitle(ctx),
|
|
67
|
+
type: metric.type,
|
|
68
|
+
entries,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
await this.cacheService.set(cacheKey, metrics, { ttl: 1000 * 60 * 60 * 2 }); // 2 hours
|
|
72
|
+
return metrics;
|
|
73
|
+
}
|
|
74
|
+
async loadData(ctx, interval, endDate) {
|
|
75
|
+
let nrOfEntries;
|
|
76
|
+
let backInTimeAmount;
|
|
77
|
+
const orderRepo = this.connection.getRepository(ctx, core_1.Order);
|
|
78
|
+
// What function to use to get the current Tick of a date (i.e. the week or month number)
|
|
79
|
+
let getTickNrFn;
|
|
80
|
+
let maxTick;
|
|
81
|
+
switch (interval) {
|
|
82
|
+
case types_js_1.MetricInterval.Daily: {
|
|
83
|
+
nrOfEntries = 30;
|
|
84
|
+
backInTimeAmount = { days: nrOfEntries };
|
|
85
|
+
getTickNrFn = date_fns_1.getDayOfYear;
|
|
86
|
+
maxTick = 365;
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
default:
|
|
90
|
+
(0, shared_utils_1.assertNever)(interval);
|
|
91
|
+
}
|
|
92
|
+
const startDate = (0, date_fns_1.startOfDay)((0, date_fns_1.sub)(endDate, backInTimeAmount));
|
|
93
|
+
const startTick = getTickNrFn(startDate);
|
|
94
|
+
// Get orders in a loop until we have all
|
|
95
|
+
let skip = 0;
|
|
96
|
+
const take = 1000;
|
|
97
|
+
let hasMoreOrders = true;
|
|
98
|
+
const orders = [];
|
|
99
|
+
while (hasMoreOrders) {
|
|
100
|
+
const query = orderRepo
|
|
101
|
+
.createQueryBuilder('order')
|
|
102
|
+
.leftJoin('order.channels', 'orderChannel')
|
|
103
|
+
.where('orderChannel.id=:channelId', { channelId: ctx.channelId })
|
|
104
|
+
.andWhere('order.orderPlacedAt >= :startDate', {
|
|
105
|
+
startDate: startDate.toISOString(),
|
|
106
|
+
})
|
|
107
|
+
.skip(skip)
|
|
108
|
+
.take(take);
|
|
109
|
+
const [items, nrOfOrders] = await query.getManyAndCount();
|
|
110
|
+
orders.push(...items);
|
|
111
|
+
core_1.Logger.verbose(`Fetched orders ${skip}-${skip + take} for channel ${ctx.channel.token} for ${interval} metrics`, constants_js_1.loggerCtx);
|
|
112
|
+
skip += items.length;
|
|
113
|
+
if (orders.length >= nrOfOrders) {
|
|
114
|
+
hasMoreOrders = false;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
core_1.Logger.verbose(`Finished fetching all ${orders.length} orders for channel ${ctx.channel.token} for ${interval} metrics`, constants_js_1.loggerCtx);
|
|
118
|
+
const dataPerInterval = new Map();
|
|
119
|
+
const ticks = [];
|
|
120
|
+
for (let i = 1; i <= nrOfEntries; i++) {
|
|
121
|
+
if (startTick + i >= maxTick) {
|
|
122
|
+
// make sure we don't go over month 12 or week 52
|
|
123
|
+
ticks.push(startTick + i - maxTick);
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
ticks.push(startTick + i);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
ticks.forEach(tick => {
|
|
130
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
131
|
+
const ordersInCurrentTick = orders.filter(order => getTickNrFn(order.orderPlacedAt) === tick);
|
|
132
|
+
dataPerInterval.set(tick, {
|
|
133
|
+
orders: ordersInCurrentTick,
|
|
134
|
+
date: (0, date_fns_1.setDayOfYear)(endDate, tick),
|
|
135
|
+
});
|
|
136
|
+
});
|
|
137
|
+
return dataPerInterval;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
exports.MetricsService = MetricsService;
|
|
141
|
+
exports.MetricsService = MetricsService = __decorate([
|
|
142
|
+
(0, common_1.Injectable)(),
|
|
143
|
+
__metadata("design:paramtypes", [core_1.TransactionalConnection,
|
|
144
|
+
core_1.CacheService])
|
|
145
|
+
], MetricsService);
|
package/dist/plugin/types.d.ts
CHANGED
|
@@ -1,40 +1,23 @@
|
|
|
1
|
-
export type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export type MetricSummary = {
|
|
2
|
+
interval: MetricInterval;
|
|
3
|
+
type: MetricType;
|
|
4
|
+
title: string;
|
|
5
|
+
entries: MetricSummaryEntry[];
|
|
6
6
|
};
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
export declare enum MetricType {
|
|
8
|
+
OrderCount = "OrderCount",
|
|
9
|
+
OrderTotal = "OrderTotal",
|
|
10
|
+
AverageOrderValue = "AverageOrderValue"
|
|
11
|
+
}
|
|
12
|
+
export declare enum MetricInterval {
|
|
13
|
+
Daily = "Daily"
|
|
14
|
+
}
|
|
15
|
+
export type MetricSummaryEntry = {
|
|
16
|
+
label: string;
|
|
17
|
+
value: number;
|
|
13
18
|
};
|
|
14
|
-
export
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}) => string;
|
|
19
|
-
export type TransformTsConfigPathMappingsFn = (params: {
|
|
20
|
-
phase: 'compiling' | 'loading';
|
|
21
|
-
alias: string;
|
|
22
|
-
patterns: string[];
|
|
23
|
-
}) => string[];
|
|
24
|
-
/**
|
|
25
|
-
* @description
|
|
26
|
-
* The PathAdapter interface allows customization of how paths are handled
|
|
27
|
-
* when compiling the Vendure config and its imports.
|
|
28
|
-
*/
|
|
29
|
-
export interface PathAdapter {
|
|
30
|
-
/**
|
|
31
|
-
* @description
|
|
32
|
-
* A function to determine the path to the compiled Vendure config file.
|
|
33
|
-
*/
|
|
34
|
-
getCompiledConfigPath?: GetCompiledConfigPathFn;
|
|
35
|
-
/**
|
|
36
|
-
* If your project makes use of the TypeScript `paths` configuration, the compiler will
|
|
37
|
-
* attempt to use these paths when compiling the Vendure config and its imports.
|
|
38
|
-
*/
|
|
39
|
-
transformTsConfigPathMappings?: TransformTsConfigPathMappingsFn;
|
|
19
|
+
export interface MetricSummaryInput {
|
|
20
|
+
interval: MetricInterval;
|
|
21
|
+
types: MetricType[];
|
|
22
|
+
refresh?: boolean;
|
|
40
23
|
}
|
package/dist/plugin/types.js
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MetricInterval = exports.MetricType = void 0;
|
|
4
|
+
var MetricType;
|
|
5
|
+
(function (MetricType) {
|
|
6
|
+
MetricType["OrderCount"] = "OrderCount";
|
|
7
|
+
MetricType["OrderTotal"] = "OrderTotal";
|
|
8
|
+
MetricType["AverageOrderValue"] = "AverageOrderValue";
|
|
9
|
+
})(MetricType || (exports.MetricType = MetricType = {}));
|
|
10
|
+
var MetricInterval;
|
|
11
|
+
(function (MetricInterval) {
|
|
12
|
+
MetricInterval["Daily"] = "Daily";
|
|
13
|
+
})(MetricInterval || (exports.MetricInterval = MetricInterval = {}));
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { LanguageCode } from '@vendure/core';
|
|
2
|
+
export declare const defaultLanguage = LanguageCode.en;
|
|
3
|
+
export declare const defaultLocale: undefined;
|
|
4
|
+
export declare const defaultAvailableLanguages: LanguageCode[];
|
|
5
|
+
export declare const defaultAvailableLocales: string[];
|