@commercelayer/cli-plugin-metrics 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 +21 -0
- package/README.md +1 -0
- package/bin/run.cmd +3 -0
- package/bin/run.js +6 -0
- package/lib/base.d.ts +47 -0
- package/lib/base.js +183 -0
- package/lib/commands/metrics/breakdown.d.ts +18 -0
- package/lib/commands/metrics/breakdown.js +103 -0
- package/lib/commands/metrics/date_breakdown.d.ts +16 -0
- package/lib/commands/metrics/date_breakdown.js +80 -0
- package/lib/commands/metrics/fbt.d.ts +11 -0
- package/lib/commands/metrics/fbt.js +51 -0
- package/lib/commands/metrics/noc.d.ts +6 -0
- package/lib/commands/metrics/noc.js +13 -0
- package/lib/commands/metrics/search.d.ts +19 -0
- package/lib/commands/metrics/search.js +76 -0
- package/lib/commands/metrics/stats.d.ts +17 -0
- package/lib/commands/metrics/stats.js +80 -0
- package/lib/common.d.ts +117 -0
- package/lib/common.js +30 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +4 -0
- package/lib/request.d.ts +2 -0
- package/lib/request.js +27 -0
- package/oclif.manifest.json +674 -0
- package/package.json +87 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
const base_1 = require("../../base");
|
|
5
|
+
const common_1 = require("../../common");
|
|
6
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
7
|
+
const request_1 = require("../../request");
|
|
8
|
+
class MetricsSearch extends base_1.BaseResourceCommand {
|
|
9
|
+
static operation = 'search';
|
|
10
|
+
static aliases = [MetricsSearch.operation];
|
|
11
|
+
static description = 'perform a search query on the Metrics API endpoint';
|
|
12
|
+
static examples = [
|
|
13
|
+
'commercelayewr metrics:search orders -l 5 -s asc -b order.placed_at -f order.id,order.number,order.placed_at,customer.email'
|
|
14
|
+
];
|
|
15
|
+
static flags = {
|
|
16
|
+
limit: core_1.Flags.integer({
|
|
17
|
+
char: 'l',
|
|
18
|
+
description: 'the maximum number of records shown in the response',
|
|
19
|
+
min: 1,
|
|
20
|
+
max: 100
|
|
21
|
+
}),
|
|
22
|
+
sort: core_1.Flags.string({
|
|
23
|
+
char: 's',
|
|
24
|
+
description: 'the way you want the results of the query to be sorted',
|
|
25
|
+
options: common_1.sorts,
|
|
26
|
+
dependsOn: ['sort_by']
|
|
27
|
+
}),
|
|
28
|
+
sort_by: core_1.Flags.string({
|
|
29
|
+
char: 'b',
|
|
30
|
+
description: 'the date field you want the results of the query sorted by'
|
|
31
|
+
}),
|
|
32
|
+
fields: core_1.Flags.string({
|
|
33
|
+
char: 'f',
|
|
34
|
+
description: 'comma-separated list of fields you want to be returned for each record in the response',
|
|
35
|
+
required: true,
|
|
36
|
+
multiple: true
|
|
37
|
+
}),
|
|
38
|
+
cursor: core_1.Flags.string({
|
|
39
|
+
char: 'c',
|
|
40
|
+
description: 'the cursor pointing to a specific page in the paginated search results'
|
|
41
|
+
})
|
|
42
|
+
};
|
|
43
|
+
static args = {
|
|
44
|
+
...base_1.BaseResourceCommand.args
|
|
45
|
+
};
|
|
46
|
+
async run() {
|
|
47
|
+
const { args, flags } = await this.parse(MetricsSearch);
|
|
48
|
+
this.checkAcessTokenData(flags.accessToken, flags);
|
|
49
|
+
const resource = args.resource;
|
|
50
|
+
const fields = this.multivalFlag(flags.fields);
|
|
51
|
+
const querySearch = {
|
|
52
|
+
fields,
|
|
53
|
+
limit: flags.limit,
|
|
54
|
+
sort: flags.sort,
|
|
55
|
+
sort_by: flags.sort_by,
|
|
56
|
+
cursor: flags.cursor
|
|
57
|
+
};
|
|
58
|
+
const filterObject = this.filterFlag(flags.filter);
|
|
59
|
+
const query = {
|
|
60
|
+
search: querySearch,
|
|
61
|
+
filter: filterObject
|
|
62
|
+
};
|
|
63
|
+
const response = await (0, request_1.metricsRequest)(MetricsSearch.operation, query, resource, flags);
|
|
64
|
+
const res = response.clone();
|
|
65
|
+
await this.printResponse(response);
|
|
66
|
+
// Print pagination info
|
|
67
|
+
if (res.ok) {
|
|
68
|
+
const pagination = (await res.json()).meta.pagination;
|
|
69
|
+
this.log(`Record count: ${cli_core_1.clColor.yellowBright(pagination.record_count)}`);
|
|
70
|
+
if (pagination.cursor)
|
|
71
|
+
this.log(`Cursor: ${cli_core_1.clColor.cyanBright(pagination.cursor)}`);
|
|
72
|
+
this.log();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.default = MetricsSearch;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { BaseResourceCommand } from '../../base';
|
|
2
|
+
import type { MetricsOperation } from '../../common';
|
|
3
|
+
export default class MetricsStats extends BaseResourceCommand {
|
|
4
|
+
static operation: MetricsOperation;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
field: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
operator: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
description: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
static args: {
|
|
14
|
+
resource: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const core_1 = require("@oclif/core");
|
|
5
|
+
const base_1 = require("../../base");
|
|
6
|
+
const common_1 = require("../../common");
|
|
7
|
+
const cliux = tslib_1.__importStar(require("@commercelayer/cli-ux"));
|
|
8
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
9
|
+
const request_1 = require("../../request");
|
|
10
|
+
class MetricsStats extends base_1.BaseResourceCommand {
|
|
11
|
+
static operation = 'stats';
|
|
12
|
+
static aliases = [MetricsStats.operation];
|
|
13
|
+
static description = 'perform a stats query on the Metrics API endpoint';
|
|
14
|
+
static examples = [
|
|
15
|
+
'commercelayer metrics:stats orders -f order.total_amount_with_taxes --op avg',
|
|
16
|
+
'cl stats orders -f order.total_amount_with_taxes -O stats'
|
|
17
|
+
];
|
|
18
|
+
static flags = {
|
|
19
|
+
field: core_1.Flags.string({
|
|
20
|
+
char: 'f',
|
|
21
|
+
description: 'the field you want the metrics or statistics computed on',
|
|
22
|
+
required: true
|
|
23
|
+
}),
|
|
24
|
+
operator: core_1.Flags.string({
|
|
25
|
+
char: 'O',
|
|
26
|
+
aliases: ['op'],
|
|
27
|
+
description: 'the computing operator',
|
|
28
|
+
options: common_1.operators,
|
|
29
|
+
required: true
|
|
30
|
+
}),
|
|
31
|
+
description: core_1.Flags.boolean({
|
|
32
|
+
char: 'D',
|
|
33
|
+
description: 'show the description of the operator used for the query',
|
|
34
|
+
hidden: true
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
static args = {
|
|
38
|
+
...base_1.BaseResourceCommand.args
|
|
39
|
+
};
|
|
40
|
+
async run() {
|
|
41
|
+
const { args, flags } = await this.parse(MetricsStats);
|
|
42
|
+
this.checkAcessTokenData(flags.accessToken, flags);
|
|
43
|
+
const resource = args.resource;
|
|
44
|
+
const field = flags.field;
|
|
45
|
+
const operator = flags.operator;
|
|
46
|
+
const queryStats = {
|
|
47
|
+
field,
|
|
48
|
+
operator
|
|
49
|
+
};
|
|
50
|
+
const filterObject = this.filterFlag(flags.filter);
|
|
51
|
+
const query = {
|
|
52
|
+
stats: queryStats,
|
|
53
|
+
filter: filterObject
|
|
54
|
+
};
|
|
55
|
+
const response = await (0, request_1.metricsRequest)(MetricsStats.operation, query, resource, flags);
|
|
56
|
+
if (response.ok) {
|
|
57
|
+
cliux.action.stop(cli_core_1.clColor.msg.success('Done'));
|
|
58
|
+
const operatorInfo = common_1.operatorMap[operator];
|
|
59
|
+
if (flags.description)
|
|
60
|
+
this.log(cli_core_1.clColor.italic(`\n${operatorInfo.description}`));
|
|
61
|
+
const func = `${cli_core_1.clColor.cyan(`${operator}(`)}${cli_core_1.clColor.italic(field)}${cli_core_1.clColor.cyan(')')}`;
|
|
62
|
+
const jsonRes = await response.json();
|
|
63
|
+
const value = jsonRes.data.value;
|
|
64
|
+
this.log();
|
|
65
|
+
if (operatorInfo.type === 'Object') {
|
|
66
|
+
this.log(`${func} = {`);
|
|
67
|
+
['count', 'min', 'max', 'avg', 'sum'].forEach((op) => {
|
|
68
|
+
this.log(` ${op.padStart(5, ' ')}: ${cli_core_1.clColor.yellow(value[op])}`);
|
|
69
|
+
});
|
|
70
|
+
this.log('}');
|
|
71
|
+
}
|
|
72
|
+
else
|
|
73
|
+
this.log(`${func} = ${cli_core_1.clColor.yellow(value)}`);
|
|
74
|
+
this.log();
|
|
75
|
+
}
|
|
76
|
+
else
|
|
77
|
+
await this.printResponse(response);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.default = MetricsStats;
|
package/lib/common.d.ts
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
export declare const analysisOperations: string[];
|
|
2
|
+
declare const operationList: readonly ["search", "stats", "breakdown", "date_breakdown", ...string[]];
|
|
3
|
+
export type MetricsOperation = typeof operationList[number];
|
|
4
|
+
export declare const operations: string[];
|
|
5
|
+
declare const resourceList: readonly ["orders", "returns", "carts"];
|
|
6
|
+
export type MetricsResource = typeof resourceList[number];
|
|
7
|
+
export declare const resources: string[];
|
|
8
|
+
declare const intervalList: readonly ["hour", "day", "week", "month", "year"];
|
|
9
|
+
export type MetricsInterval = typeof intervalList[number];
|
|
10
|
+
export declare const intervals: string[];
|
|
11
|
+
export declare const operatorMap: {
|
|
12
|
+
readonly avg: {
|
|
13
|
+
readonly type: "Float";
|
|
14
|
+
readonly description: "A single-value metrics aggregation that computes the average of numeric values extracted from specific numeric fields of the aggregated records";
|
|
15
|
+
};
|
|
16
|
+
readonly cardinality: {
|
|
17
|
+
readonly type: "Integer";
|
|
18
|
+
readonly description: "A single-value metrics aggregation that calculates an approximate count of distinct values";
|
|
19
|
+
};
|
|
20
|
+
readonly max: {
|
|
21
|
+
readonly type: "Float";
|
|
22
|
+
readonly description: "A single-value metrics aggregation that keeps track and returns the maximum value among the numeric values extracted from specific numeric fields of the aggregated records";
|
|
23
|
+
};
|
|
24
|
+
readonly min: {
|
|
25
|
+
readonly type: "Float";
|
|
26
|
+
readonly description: "A single-value metrics aggregation that keeps track and returns the minimum value among the numeric values extracted from specific numeric fields of the aggregated records";
|
|
27
|
+
};
|
|
28
|
+
readonly percentiles: {
|
|
29
|
+
readonly type: "Float";
|
|
30
|
+
readonly description: "A multi-value metrics aggregation that calculates one or more percentiles (i.e. the point at which a certain percentage of observed values occurs) over numeric values extracted from specific numeric fields of the aggregated records";
|
|
31
|
+
};
|
|
32
|
+
readonly stats: {
|
|
33
|
+
readonly type: "Object";
|
|
34
|
+
readonly description: "A multi-value metrics aggregation that computes stats over numeric values extracted from specific numeric fields of the aggregated records. The stats that are returned consist of: count, min, max, avg, and sum";
|
|
35
|
+
};
|
|
36
|
+
readonly sum: {
|
|
37
|
+
readonly type: "Float";
|
|
38
|
+
readonly description: "A single-value metrics aggregation that sums up numeric values extracted from specific numeric fields of the aggregated records";
|
|
39
|
+
};
|
|
40
|
+
readonly value_count: {
|
|
41
|
+
readonly type: "Integer";
|
|
42
|
+
readonly description: "A single-value metrics aggregation that counts the number of values extracted from specific fields of the aggregated records";
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
export type MetricsOperator = keyof typeof operatorMap;
|
|
46
|
+
export declare const operators: string[];
|
|
47
|
+
declare const conditionList: readonly ["eq", "ne", "gt", "gte", "lt", "lte", "gt_lt", "gte_lte", "gte_lt", "gt_lte"];
|
|
48
|
+
export type MetricsConditionKey = typeof conditionList[number];
|
|
49
|
+
export declare const conditions: string[];
|
|
50
|
+
export type MetricsCondition = {
|
|
51
|
+
[key in MetricsConditionKey]?: (number | [number, number]);
|
|
52
|
+
};
|
|
53
|
+
declare const sortList: readonly ["asc", "desc"];
|
|
54
|
+
export type MetricsSort = typeof sortList[number];
|
|
55
|
+
export declare const sorts: string[];
|
|
56
|
+
export type MetricsQuerySearch = {
|
|
57
|
+
limit?: number;
|
|
58
|
+
sort?: MetricsSort;
|
|
59
|
+
sort_by?: string;
|
|
60
|
+
fields: string[];
|
|
61
|
+
cursor?: string;
|
|
62
|
+
};
|
|
63
|
+
export type MetricsQueryStats = {
|
|
64
|
+
field: string;
|
|
65
|
+
operator: MetricsOperator;
|
|
66
|
+
};
|
|
67
|
+
export type MetricsQueryBreakdown = {
|
|
68
|
+
by: string;
|
|
69
|
+
field: string;
|
|
70
|
+
operator: MetricsOperator;
|
|
71
|
+
condition?: MetricsCondition;
|
|
72
|
+
sort?: MetricsSort;
|
|
73
|
+
limit?: number;
|
|
74
|
+
breakdown?: MetricsQueryBreakdown;
|
|
75
|
+
};
|
|
76
|
+
export type MetricsQueryBreakdownResponse = {
|
|
77
|
+
label: string;
|
|
78
|
+
value: string | number;
|
|
79
|
+
} & {
|
|
80
|
+
key?: MetricsQueryBreakdown;
|
|
81
|
+
};
|
|
82
|
+
export type MetricsQueryDateBreakdown = {
|
|
83
|
+
by: string;
|
|
84
|
+
field: string;
|
|
85
|
+
operator: MetricsOperator;
|
|
86
|
+
interval?: MetricsInterval;
|
|
87
|
+
breakdown?: MetricsQueryBreakdown;
|
|
88
|
+
};
|
|
89
|
+
export type MetricsQueryDateBreakdownResponse = {
|
|
90
|
+
date: string;
|
|
91
|
+
value: any;
|
|
92
|
+
} & {
|
|
93
|
+
key?: MetricsQueryBreakdown;
|
|
94
|
+
};
|
|
95
|
+
export type MetricsFilter = Record<string, any>;
|
|
96
|
+
export type MetricsFilterFbt = {
|
|
97
|
+
line_items: {
|
|
98
|
+
item_ids: {
|
|
99
|
+
in: string[];
|
|
100
|
+
};
|
|
101
|
+
};
|
|
102
|
+
};
|
|
103
|
+
export type MetricsQueryFbt = {
|
|
104
|
+
filter: MetricsFilterFbt;
|
|
105
|
+
};
|
|
106
|
+
export type MetricsQuery = (({
|
|
107
|
+
search: MetricsQuerySearch;
|
|
108
|
+
} | {
|
|
109
|
+
stats: MetricsQueryStats;
|
|
110
|
+
} | {
|
|
111
|
+
breakdown: MetricsQueryBreakdown;
|
|
112
|
+
} | {
|
|
113
|
+
date_breakdown: MetricsQueryDateBreakdown;
|
|
114
|
+
}) & {
|
|
115
|
+
filter?: MetricsFilter;
|
|
116
|
+
}) | MetricsQueryFbt;
|
|
117
|
+
export {};
|
package/lib/common.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sorts = exports.conditions = exports.operators = exports.operatorMap = exports.intervals = exports.resources = exports.operations = exports.analysisOperations = void 0;
|
|
4
|
+
// Operations
|
|
5
|
+
exports.analysisOperations = ['fbt'];
|
|
6
|
+
const operationList = ['search', 'stats', 'breakdown', 'date_breakdown', ...exports.analysisOperations];
|
|
7
|
+
exports.operations = operationList;
|
|
8
|
+
// Resources
|
|
9
|
+
const resourceList = ['orders', 'returns', 'carts'];
|
|
10
|
+
exports.resources = resourceList;
|
|
11
|
+
// Intervals
|
|
12
|
+
const intervalList = ['hour', 'day', 'week', 'month', 'year'];
|
|
13
|
+
exports.intervals = intervalList;
|
|
14
|
+
// Operators
|
|
15
|
+
exports.operatorMap = {
|
|
16
|
+
avg: { type: 'Float', description: 'A single-value metrics aggregation that computes the average of numeric values extracted from specific numeric fields of the aggregated records' },
|
|
17
|
+
cardinality: { type: 'Integer', description: 'A single-value metrics aggregation that calculates an approximate count of distinct values' },
|
|
18
|
+
max: { type: 'Float', description: 'A single-value metrics aggregation that keeps track and returns the maximum value among the numeric values extracted from specific numeric fields of the aggregated records' },
|
|
19
|
+
min: { type: 'Float', description: 'A single-value metrics aggregation that keeps track and returns the minimum value among the numeric values extracted from specific numeric fields of the aggregated records' },
|
|
20
|
+
percentiles: { type: 'Float', description: 'A multi-value metrics aggregation that calculates one or more percentiles (i.e. the point at which a certain percentage of observed values occurs) over numeric values extracted from specific numeric fields of the aggregated records' },
|
|
21
|
+
stats: { type: 'Object', description: 'A multi-value metrics aggregation that computes stats over numeric values extracted from specific numeric fields of the aggregated records. The stats that are returned consist of: count, min, max, avg, and sum' },
|
|
22
|
+
sum: { type: 'Float', description: 'A single-value metrics aggregation that sums up numeric values extracted from specific numeric fields of the aggregated records' },
|
|
23
|
+
value_count: { type: 'Integer', description: 'A single-value metrics aggregation that counts the number of values extracted from specific fields of the aggregated records' }
|
|
24
|
+
};
|
|
25
|
+
exports.operators = Object.keys(exports.operatorMap);
|
|
26
|
+
// Conditions
|
|
27
|
+
const conditionList = ['eq', 'ne', 'gt', 'gte', 'lt', 'lte', 'gt_lt', 'gte_lte', 'gte_lt', 'gt_lte'];
|
|
28
|
+
exports.conditions = conditionList;
|
|
29
|
+
const sortList = ['asc', 'desc'];
|
|
30
|
+
exports.sorts = sortList;
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { run } from '@oclif/core';
|
package/lib/index.js
ADDED
package/lib/request.d.ts
ADDED
package/lib/request.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.metricsRequest = metricsRequest;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
6
|
+
const common_1 = require("./common");
|
|
7
|
+
const cliux = tslib_1.__importStar(require("@commercelayer/cli-ux"));
|
|
8
|
+
async function metricsRequest(operation, query, resource, flags) {
|
|
9
|
+
console.log();
|
|
10
|
+
cliux.action.start(`Performing ${cli_core_1.clColor.yellow(operation)} operation ${resource ? `on ${cli_core_1.clColor.api.resource(resource)}` : ''}`);
|
|
11
|
+
const baseUrl = cli_core_1.clApi.baseURL('metrics', flags.organization, flags.domain);
|
|
12
|
+
const analysisPath = common_1.analysisOperations.includes(operation) ? 'analysis/' : '';
|
|
13
|
+
const resourcePath = resource ? `${resource}/` : '';
|
|
14
|
+
const endpoint = `${baseUrl}/${cli_core_1.clConfig.metrics.default_path}/${resourcePath}${analysisPath}${operation}`;
|
|
15
|
+
const body = JSON.stringify(query);
|
|
16
|
+
const headers = {
|
|
17
|
+
'Accept': 'application/vnd.api.v1+json',
|
|
18
|
+
'Content-Type': 'application/vnd.api+json',
|
|
19
|
+
'Authorization': `Bearer ${flags.accessToken}`
|
|
20
|
+
};
|
|
21
|
+
const response = fetch(endpoint, {
|
|
22
|
+
method: "POST",
|
|
23
|
+
headers,
|
|
24
|
+
body
|
|
25
|
+
});
|
|
26
|
+
return await response;
|
|
27
|
+
}
|