@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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [2025] [Commerce Layer]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# commercelayer-cli-plugin-links
|
package/bin/run.cmd
ADDED
package/bin/run.js
ADDED
package/lib/base.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { type CommerceLayerClient } from '@commercelayer/sdk';
|
|
2
|
+
import { Command, Args, Flags } from '@oclif/core';
|
|
3
|
+
import { type MetricsFilter, type MetricsQueryBreakdown } from './common';
|
|
4
|
+
export declare abstract class BaseCommand extends Command {
|
|
5
|
+
static baseFlags: {
|
|
6
|
+
organization: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
7
|
+
domain: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
8
|
+
accessToken: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
init(): Promise<any>;
|
|
11
|
+
catch(error: any): Promise<any>;
|
|
12
|
+
protected handleError(error: any, flags?: any): Promise<any>;
|
|
13
|
+
protected commercelayerInit(flags: any): CommerceLayerClient;
|
|
14
|
+
protected checkAcessTokenData(accessToken: string, flags?: any): boolean;
|
|
15
|
+
protected multivalFlag(flag?: string[]): string[];
|
|
16
|
+
protected printResponse(response: Response): Promise<void>;
|
|
17
|
+
}
|
|
18
|
+
export declare abstract class BaseResourceCommand extends BaseCommand {
|
|
19
|
+
static baseFlags: {
|
|
20
|
+
filter: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
21
|
+
organization: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
22
|
+
domain: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
23
|
+
accessToken: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
24
|
+
};
|
|
25
|
+
static args: {
|
|
26
|
+
resource: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
27
|
+
};
|
|
28
|
+
protected filterFlag(flag?: string): MetricsFilter | undefined;
|
|
29
|
+
}
|
|
30
|
+
export declare abstract class BaseBreakdownCommand extends BaseResourceCommand {
|
|
31
|
+
static baseFlags: {
|
|
32
|
+
by: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
33
|
+
field: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
34
|
+
operator: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
35
|
+
breakdown: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
36
|
+
filter: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
37
|
+
organization: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
38
|
+
domain: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
39
|
+
accessToken: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
40
|
+
};
|
|
41
|
+
static args: {
|
|
42
|
+
resource: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
43
|
+
};
|
|
44
|
+
protected breakdownFlag(flag?: string): MetricsQueryBreakdown | undefined;
|
|
45
|
+
protected printBreakdown(by: string, data: any, level?: number): void;
|
|
46
|
+
}
|
|
47
|
+
export { Args, Flags };
|
package/lib/base.js
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Flags = exports.Args = exports.BaseBreakdownCommand = exports.BaseResourceCommand = exports.BaseCommand = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const sdk_1 = tslib_1.__importStar(require("@commercelayer/sdk"));
|
|
6
|
+
const core_1 = require("@oclif/core");
|
|
7
|
+
Object.defineProperty(exports, "Args", { enumerable: true, get: function () { return core_1.Args; } });
|
|
8
|
+
Object.defineProperty(exports, "Flags", { enumerable: true, get: function () { return core_1.Flags; } });
|
|
9
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
10
|
+
const common_1 = require("./common");
|
|
11
|
+
const cliux = tslib_1.__importStar(require("@commercelayer/cli-ux"));
|
|
12
|
+
const pkg = require('../package.json');
|
|
13
|
+
const REQUIRED_APP_KIND = cli_core_1.clConfig.metrics.applications;
|
|
14
|
+
class BaseCommand extends core_1.Command {
|
|
15
|
+
static baseFlags = {
|
|
16
|
+
organization: core_1.Flags.string({
|
|
17
|
+
char: 'o',
|
|
18
|
+
description: 'the slug of your organization',
|
|
19
|
+
required: true,
|
|
20
|
+
env: 'CL_CLI_ORGANIZATION',
|
|
21
|
+
hidden: true
|
|
22
|
+
}),
|
|
23
|
+
domain: core_1.Flags.string({
|
|
24
|
+
char: 'd',
|
|
25
|
+
required: false,
|
|
26
|
+
hidden: true,
|
|
27
|
+
dependsOn: ['organization'],
|
|
28
|
+
env: 'CL_CLI_DOMAIN'
|
|
29
|
+
}),
|
|
30
|
+
accessToken: core_1.Flags.string({
|
|
31
|
+
char: 'a',
|
|
32
|
+
description: 'custom access token to use instead of the one used for login',
|
|
33
|
+
hidden: true,
|
|
34
|
+
required: true,
|
|
35
|
+
env: 'CL_CLI_ACCESS_TOKEN',
|
|
36
|
+
dependsOn: ['organization']
|
|
37
|
+
})
|
|
38
|
+
};
|
|
39
|
+
// INIT (override)
|
|
40
|
+
async init() {
|
|
41
|
+
cli_core_1.clUpdate.checkUpdate(pkg);
|
|
42
|
+
return await super.init();
|
|
43
|
+
}
|
|
44
|
+
async catch(error) {
|
|
45
|
+
return await this.handleError(error);
|
|
46
|
+
}
|
|
47
|
+
async handleError(error, flags) {
|
|
48
|
+
if (sdk_1.CommerceLayerStatic.isApiError(error)) {
|
|
49
|
+
if (error.status === 401) {
|
|
50
|
+
const err = error.first();
|
|
51
|
+
this.error(cli_core_1.clColor.msg.error(`${err.title}: ${err.detail}`), { suggestions: ['Execute login to get access to the organization\'s resources'] });
|
|
52
|
+
}
|
|
53
|
+
else
|
|
54
|
+
this.error(cli_core_1.clOutput.formatError(error, flags));
|
|
55
|
+
}
|
|
56
|
+
else
|
|
57
|
+
return await super.catch(error);
|
|
58
|
+
}
|
|
59
|
+
commercelayerInit(flags) {
|
|
60
|
+
const organization = flags.organization;
|
|
61
|
+
const domain = flags.domain;
|
|
62
|
+
const accessToken = flags.accessToken;
|
|
63
|
+
const userAgent = cli_core_1.clUtil.userAgent(this.config);
|
|
64
|
+
return (0, sdk_1.default)({
|
|
65
|
+
organization,
|
|
66
|
+
domain,
|
|
67
|
+
accessToken,
|
|
68
|
+
userAgent
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
checkAcessTokenData(accessToken, flags) {
|
|
72
|
+
const info = cli_core_1.clToken.decodeAccessToken(accessToken);
|
|
73
|
+
if (info === null)
|
|
74
|
+
this.error('Invalid access token provided');
|
|
75
|
+
else if (!REQUIRED_APP_KIND.includes(info.application.kind)) // Application
|
|
76
|
+
this.error(`Invalid application kind: ${cli_core_1.clColor.msg.error(info.application.kind)}. Only these access tokens can be used: [${REQUIRED_APP_KIND.join(', ')}]`);
|
|
77
|
+
else if (info.organization?.slug !== flags.organization) // Organization
|
|
78
|
+
this.error(`The access token provided belongs to a wrong organization: ${cli_core_1.clColor.msg.error(info.organization?.slug)} instead of ${cli_core_1.clColor.style.organization(flags.organization)}`);
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
multivalFlag(flag) {
|
|
82
|
+
const values = [];
|
|
83
|
+
if (flag) {
|
|
84
|
+
const flagValues = flag.map(f => f.split(',').map(t => t.trim()));
|
|
85
|
+
flagValues.forEach(a => values.push(...a));
|
|
86
|
+
}
|
|
87
|
+
return values;
|
|
88
|
+
}
|
|
89
|
+
async printResponse(response) {
|
|
90
|
+
if (cliux.action.running)
|
|
91
|
+
cliux.action.stop(response.ok ? cli_core_1.clColor.msg.success('Done') : cli_core_1.clColor.msg.error('Error'));
|
|
92
|
+
const jsonRes = await response.json();
|
|
93
|
+
this.log();
|
|
94
|
+
if (response.ok)
|
|
95
|
+
this.log(cli_core_1.clOutput.formatOutput(jsonRes.data));
|
|
96
|
+
else
|
|
97
|
+
this.log(cli_core_1.clOutput.formatError(jsonRes));
|
|
98
|
+
this.log();
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
exports.BaseCommand = BaseCommand;
|
|
102
|
+
class BaseResourceCommand extends BaseCommand {
|
|
103
|
+
static baseFlags = {
|
|
104
|
+
...BaseCommand.baseFlags,
|
|
105
|
+
filter: core_1.Flags.string({
|
|
106
|
+
char: 'F',
|
|
107
|
+
description: 'the filter to apply to the query in JSON format (enclosed in single quotes)'
|
|
108
|
+
})
|
|
109
|
+
};
|
|
110
|
+
static args = {
|
|
111
|
+
resource: core_1.Args.string({ resource: 'the resource name', options: common_1.resources, required: true })
|
|
112
|
+
};
|
|
113
|
+
filterFlag(flag) {
|
|
114
|
+
let filter;
|
|
115
|
+
if (flag) {
|
|
116
|
+
try {
|
|
117
|
+
filter = JSON.parse(flag);
|
|
118
|
+
}
|
|
119
|
+
catch (error) {
|
|
120
|
+
this.error(`Invalid ${cli_core_1.clColor.cli.flag('filter')} format. Please provide a valid JSON string`);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return filter;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.BaseResourceCommand = BaseResourceCommand;
|
|
127
|
+
class BaseBreakdownCommand extends BaseResourceCommand {
|
|
128
|
+
static baseFlags = {
|
|
129
|
+
...BaseResourceCommand.baseFlags,
|
|
130
|
+
by: core_1.Flags.string({
|
|
131
|
+
char: 'b',
|
|
132
|
+
description: 'the field you want the results of the query aggragated by',
|
|
133
|
+
required: true
|
|
134
|
+
}),
|
|
135
|
+
field: core_1.Flags.string({
|
|
136
|
+
char: 'f',
|
|
137
|
+
description: 'the field you want the metrics or statistics computed on',
|
|
138
|
+
required: true
|
|
139
|
+
}),
|
|
140
|
+
operator: core_1.Flags.string({
|
|
141
|
+
char: 'O',
|
|
142
|
+
aliases: ['op'],
|
|
143
|
+
summary: 'the computing operator',
|
|
144
|
+
description: 'the list of valid operators depends on the value of the field key',
|
|
145
|
+
options: common_1.operators,
|
|
146
|
+
required: true,
|
|
147
|
+
}),
|
|
148
|
+
breakdown: core_1.Flags.string({
|
|
149
|
+
char: 'B',
|
|
150
|
+
summary: 'the optional nested breakdown',
|
|
151
|
+
description: 'a JSON object (enclosed in single quotes) containing the nested breakdown',
|
|
152
|
+
})
|
|
153
|
+
};
|
|
154
|
+
static args = {
|
|
155
|
+
...BaseResourceCommand.args
|
|
156
|
+
};
|
|
157
|
+
breakdownFlag(flag) {
|
|
158
|
+
let breakdown;
|
|
159
|
+
if (flag) {
|
|
160
|
+
try {
|
|
161
|
+
breakdown = JSON.parse(flag);
|
|
162
|
+
}
|
|
163
|
+
catch (error) {
|
|
164
|
+
this.error(`Invalid ${cli_core_1.clColor.msg.error('breakdown')} format. Please provide a valid JSON string`);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return breakdown;
|
|
168
|
+
}
|
|
169
|
+
printBreakdown(by, data, level = 0) {
|
|
170
|
+
const tab = ' '.repeat(level);
|
|
171
|
+
this.log(`${tab}${cli_core_1.clColor.cyanBright(by)}: [`);
|
|
172
|
+
const items = data[by] || [];
|
|
173
|
+
for (const item of items) {
|
|
174
|
+
this.log(`${tab} ${item.label}: ${cli_core_1.clColor.yellow(item.value)}`);
|
|
175
|
+
const extraFields = Object.keys(item).filter((field) => !['label', 'value', 'date'].includes(String(field)));
|
|
176
|
+
const nestedBreakdown = (extraFields.length > 0) ? extraFields[0] : undefined;
|
|
177
|
+
if (nestedBreakdown)
|
|
178
|
+
this.printBreakdown(nestedBreakdown, item, level + 1);
|
|
179
|
+
}
|
|
180
|
+
this.log(`${tab}]`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.BaseBreakdownCommand = BaseBreakdownCommand;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { BaseBreakdownCommand } from '../../base';
|
|
2
|
+
import type { MetricsCondition, MetricsOperation } from '../../common';
|
|
3
|
+
export default class MetricsBreakdown extends BaseBreakdownCommand {
|
|
4
|
+
static operation: MetricsOperation;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
condition: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
sort: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
};
|
|
13
|
+
static args: {
|
|
14
|
+
resource: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
15
|
+
};
|
|
16
|
+
run(): Promise<void>;
|
|
17
|
+
protected conditionFlag(flag?: string): MetricsCondition | undefined;
|
|
18
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
5
|
+
const base_1 = require("../../base");
|
|
6
|
+
const common_1 = require("../../common");
|
|
7
|
+
const request_1 = require("../../request");
|
|
8
|
+
const cliux = tslib_1.__importStar(require("@commercelayer/cli-ux"));
|
|
9
|
+
class MetricsBreakdown extends base_1.BaseBreakdownCommand {
|
|
10
|
+
static operation = 'breakdown';
|
|
11
|
+
static aliases = ['metrics:break', MetricsBreakdown.operation];
|
|
12
|
+
static description = 'perform a breakdown query on the Metrics API endpoint';
|
|
13
|
+
static examples = [
|
|
14
|
+
'commercelayer metrics:breakdown orders -b order.country_code -f order.id -O value_count -s desc -l 20',
|
|
15
|
+
'cl breakdown orders -b order.country_code -f order.id -O value_count -s desc -l 20 -B \'{"by": "line_items.name","field": "line_items.id","operator": "value_count","sort": "desc","limit": 20}\'',
|
|
16
|
+
];
|
|
17
|
+
static flags = {
|
|
18
|
+
condition: base_1.Flags.string({
|
|
19
|
+
char: 'c',
|
|
20
|
+
summary: 'an additional constraint to fine-tune the set of records',
|
|
21
|
+
description: 'the condition is applied to the computed results of the query and it is available for operators that return single numeric (float or integer) values.'
|
|
22
|
+
}),
|
|
23
|
+
sort: base_1.Flags.string({
|
|
24
|
+
char: 's',
|
|
25
|
+
description: 'the way you want the results of the query to be sorted',
|
|
26
|
+
options: common_1.sorts
|
|
27
|
+
}),
|
|
28
|
+
limit: base_1.Flags.integer({
|
|
29
|
+
char: 'l',
|
|
30
|
+
description: 'the maximum number of records shown in the response',
|
|
31
|
+
min: 1,
|
|
32
|
+
max: 100
|
|
33
|
+
})
|
|
34
|
+
};
|
|
35
|
+
static args = {
|
|
36
|
+
...base_1.BaseResourceCommand.args
|
|
37
|
+
};
|
|
38
|
+
async run() {
|
|
39
|
+
const { args, flags } = await this.parse(MetricsBreakdown);
|
|
40
|
+
this.checkAcessTokenData(flags.accessToken, flags);
|
|
41
|
+
const resource = args.resource;
|
|
42
|
+
const operator = flags.operator;
|
|
43
|
+
const condition = this.conditionFlag(flags.condition);
|
|
44
|
+
const sort = flags.sort;
|
|
45
|
+
const breakdown = this.breakdownFlag(flags.breakdown);
|
|
46
|
+
const queryBreakdown = {
|
|
47
|
+
by: flags.by,
|
|
48
|
+
field: flags.field,
|
|
49
|
+
operator,
|
|
50
|
+
condition,
|
|
51
|
+
sort,
|
|
52
|
+
limit: flags.limit,
|
|
53
|
+
breakdown
|
|
54
|
+
};
|
|
55
|
+
const filterObject = this.filterFlag(flags.filter);
|
|
56
|
+
const query = {
|
|
57
|
+
breakdown: queryBreakdown,
|
|
58
|
+
filter: filterObject
|
|
59
|
+
};
|
|
60
|
+
const response = await (0, request_1.metricsRequest)(MetricsBreakdown.operation, query, resource, flags);
|
|
61
|
+
if (response.ok) {
|
|
62
|
+
const breakdown0 = (await response.json()).data;
|
|
63
|
+
cliux.action.stop(cli_core_1.clColor.msg.success('Done'));
|
|
64
|
+
this.log();
|
|
65
|
+
this.printBreakdown(flags.by, breakdown0);
|
|
66
|
+
this.log();
|
|
67
|
+
}
|
|
68
|
+
else
|
|
69
|
+
await this.printResponse(response);
|
|
70
|
+
}
|
|
71
|
+
conditionFlag(flag) {
|
|
72
|
+
let condition;
|
|
73
|
+
if (flag) {
|
|
74
|
+
const eqi = flag.indexOf('=');
|
|
75
|
+
if (eqi < 1)
|
|
76
|
+
this.error(`Invalid condition flag: ${cli_core_1.clColor.msg.error(flag)}`, {
|
|
77
|
+
suggestions: [`Condition flag must be defined using the format ${cli_core_1.clColor.cli.value('name=value')}`]
|
|
78
|
+
});
|
|
79
|
+
// Condition name and value
|
|
80
|
+
const name = flag.substring(0, eqi);
|
|
81
|
+
if (!common_1.conditions.includes(name))
|
|
82
|
+
this.error(`Invalid condition name: ${cli_core_1.clColor.msg.error(name)}`, {
|
|
83
|
+
suggestions: [`Condition name must be one of the following: ${cli_core_1.clColor.cli.value(common_1.conditions.join(', '))}`]
|
|
84
|
+
});
|
|
85
|
+
const value = flag.substring(eqi + 1, flag.length);
|
|
86
|
+
const usi = name.indexOf('_');
|
|
87
|
+
if (usi > 0) { // interval condition
|
|
88
|
+
const values = value.split(',');
|
|
89
|
+
if (values.length !== 2)
|
|
90
|
+
this.error(`Invalid condition value: ${cli_core_1.clColor.msg.error(value)}`, {
|
|
91
|
+
suggestions: [`Interval condition flag must be defined using the format ${cli_core_1.clColor.cli.value('name=from,to')}`]
|
|
92
|
+
});
|
|
93
|
+
const from = values[0];
|
|
94
|
+
const to = values[1];
|
|
95
|
+
condition = { [name]: [from, to] };
|
|
96
|
+
}
|
|
97
|
+
else
|
|
98
|
+
condition = { [name]: value };
|
|
99
|
+
}
|
|
100
|
+
return condition;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.default = MetricsBreakdown;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { BaseBreakdownCommand } from '../../base';
|
|
2
|
+
import type { MetricsOperator } from '../../common';
|
|
3
|
+
export default class MetricsDateBreakdown extends BaseBreakdownCommand {
|
|
4
|
+
static operation: string;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
interval: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
};
|
|
11
|
+
static args: {
|
|
12
|
+
resource: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
13
|
+
};
|
|
14
|
+
run(): Promise<void>;
|
|
15
|
+
protected printDateBreakdown(operator: MetricsOperator, data: any, level?: number): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
5
|
+
const base_1 = require("../../base");
|
|
6
|
+
const common_1 = require("../../common");
|
|
7
|
+
const request_1 = require("../../request");
|
|
8
|
+
const cliux = tslib_1.__importStar(require("@commercelayer/cli-ux"));
|
|
9
|
+
class MetricsDateBreakdown extends base_1.BaseBreakdownCommand {
|
|
10
|
+
static operation = 'date_breakdown';
|
|
11
|
+
static aliases = ['metrics:breakdate', 'metrics:date', 'breakdate', MetricsDateBreakdown.operation];
|
|
12
|
+
static description = 'perform a date breakdown query on the Metrics API endpoint';
|
|
13
|
+
static examples = [
|
|
14
|
+
'commercelayer metrics:date_breakdown orders -b order.placed_at -f order.total_amount_with_taxes -O stats -i month'
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
interval: base_1.Flags.string({
|
|
18
|
+
char: 'i',
|
|
19
|
+
description: 'the time interval over which the metrics are computed',
|
|
20
|
+
options: common_1.intervals
|
|
21
|
+
})
|
|
22
|
+
};
|
|
23
|
+
static args = {
|
|
24
|
+
...base_1.BaseResourceCommand.args
|
|
25
|
+
};
|
|
26
|
+
async run() {
|
|
27
|
+
const { args, flags } = await this.parse(MetricsDateBreakdown);
|
|
28
|
+
this.checkAcessTokenData(flags.accessToken, flags);
|
|
29
|
+
const resource = args.resource;
|
|
30
|
+
const operator = flags.operator;
|
|
31
|
+
const interval = flags.interval;
|
|
32
|
+
const breakdown = this.breakdownFlag(flags.breakdown);
|
|
33
|
+
const queryBreakdown = {
|
|
34
|
+
by: flags.by,
|
|
35
|
+
field: flags.field,
|
|
36
|
+
operator,
|
|
37
|
+
interval,
|
|
38
|
+
breakdown
|
|
39
|
+
};
|
|
40
|
+
const filterObject = this.filterFlag(flags.filter);
|
|
41
|
+
const query = {
|
|
42
|
+
date_breakdown: queryBreakdown,
|
|
43
|
+
filter: filterObject
|
|
44
|
+
};
|
|
45
|
+
const response = await (0, request_1.metricsRequest)(MetricsDateBreakdown.operation, query, resource, flags);
|
|
46
|
+
if (response.ok) {
|
|
47
|
+
const dateBreakdown = (await response.json()).data;
|
|
48
|
+
cliux.action.stop(cli_core_1.clColor.msg.success('Done'));
|
|
49
|
+
this.log();
|
|
50
|
+
this.printDateBreakdown(operator, dateBreakdown);
|
|
51
|
+
this.log();
|
|
52
|
+
}
|
|
53
|
+
else
|
|
54
|
+
await this.printResponse(response);
|
|
55
|
+
}
|
|
56
|
+
printDateBreakdown(operator, data, level = 0) {
|
|
57
|
+
if (level === 0)
|
|
58
|
+
cliux.action.stop(cli_core_1.clColor.msg.success('Done'));
|
|
59
|
+
const operatorInfo = common_1.operatorMap[operator];
|
|
60
|
+
this.log('----------------------------------------');
|
|
61
|
+
for (const item of data) {
|
|
62
|
+
this.log(`date: ${cli_core_1.clColor.magenta(cli_core_1.clOutput.cleanDate(String(item.date)))}`);
|
|
63
|
+
if (operatorInfo.type === 'Object') {
|
|
64
|
+
this.log(`${operator} = {`);
|
|
65
|
+
['count', 'min', 'max', 'avg', 'sum'].forEach((op) => {
|
|
66
|
+
this.log(` ${op.padStart(5, ' ')}: ${cli_core_1.clColor.yellow(item.value[op])}`);
|
|
67
|
+
});
|
|
68
|
+
this.log('}');
|
|
69
|
+
}
|
|
70
|
+
else
|
|
71
|
+
this.log(`${operator} = ${cli_core_1.clColor.yellow(item.value)}`);
|
|
72
|
+
const extraFields = Object.keys(item).filter((field) => !['label', 'value', 'date'].includes(String(field)));
|
|
73
|
+
const nestedBreakdown = (extraFields.length > 0) ? extraFields[0] : undefined;
|
|
74
|
+
if (nestedBreakdown)
|
|
75
|
+
this.printBreakdown(nestedBreakdown, item, level);
|
|
76
|
+
this.log('----------------------------------------');
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.default = MetricsDateBreakdown;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseCommand } from '../../base';
|
|
2
|
+
export default class MetricsFbt extends BaseCommand {
|
|
3
|
+
static operation: string;
|
|
4
|
+
static aliases: string[];
|
|
5
|
+
static description: string;
|
|
6
|
+
static examples: string[];
|
|
7
|
+
static flags: {
|
|
8
|
+
in: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
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 request_1 = require("../../request");
|
|
7
|
+
const cli_core_1 = require("@commercelayer/cli-core");
|
|
8
|
+
const cliux = tslib_1.__importStar(require("@commercelayer/cli-ux"));
|
|
9
|
+
class MetricsFbt extends base_1.BaseCommand {
|
|
10
|
+
static operation = 'fbt';
|
|
11
|
+
static aliases = [MetricsFbt.operation];
|
|
12
|
+
static description = 'perform a Frequently Bought Together query on the Metrics API analysis endpoint';
|
|
13
|
+
static examples = [
|
|
14
|
+
'commercelayer metrics:fbt --in xYZkjABcde,yzXKjYzaCx'
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
in: core_1.Flags.string({
|
|
18
|
+
char: 'i',
|
|
19
|
+
description: 'a list of SKU or bundle IDs associated as line items to one or more orders',
|
|
20
|
+
required: true,
|
|
21
|
+
multiple: true
|
|
22
|
+
})
|
|
23
|
+
};
|
|
24
|
+
async run() {
|
|
25
|
+
const { flags } = await this.parse(MetricsFbt);
|
|
26
|
+
this.checkAcessTokenData(flags.accessToken, flags);
|
|
27
|
+
const ids = this.multivalFlag(flags.in);
|
|
28
|
+
const query = {
|
|
29
|
+
filter: {
|
|
30
|
+
line_items: {
|
|
31
|
+
item_ids: {
|
|
32
|
+
in: ids
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const response = await (0, request_1.metricsRequest)(MetricsFbt.operation, query, undefined, flags);
|
|
38
|
+
if (response.ok) {
|
|
39
|
+
cliux.action.stop(cli_core_1.clColor.msg.success('Done'));
|
|
40
|
+
const jsonRes = await response.json();
|
|
41
|
+
const data = jsonRes.data;
|
|
42
|
+
if (data?.length > 0)
|
|
43
|
+
this.log(String(data));
|
|
44
|
+
else
|
|
45
|
+
this.log(cli_core_1.clColor.dim(String('\nNo data found for the given SKU or bundle IDs\n')));
|
|
46
|
+
}
|
|
47
|
+
else
|
|
48
|
+
await this.printResponse(response);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.default = MetricsFbt;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const core_1 = require("@oclif/core");
|
|
4
|
+
class Noc extends core_1.Command {
|
|
5
|
+
static hidden = true;
|
|
6
|
+
static flags = {};
|
|
7
|
+
async run() {
|
|
8
|
+
const output = '-= NoC =-';
|
|
9
|
+
this.log(output);
|
|
10
|
+
return output;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.default = Noc;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { BaseResourceCommand } from '../../base';
|
|
2
|
+
import type { MetricsOperation } from '../../common';
|
|
3
|
+
export default class MetricsSearch extends BaseResourceCommand {
|
|
4
|
+
static operation: MetricsOperation;
|
|
5
|
+
static aliases: string[];
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
limit: import("@oclif/core/lib/interfaces").OptionFlag<number | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
10
|
+
sort: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
11
|
+
sort_by: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
12
|
+
fields: import("@oclif/core/lib/interfaces").OptionFlag<string[], import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
13
|
+
cursor: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces").CustomOptions>;
|
|
14
|
+
};
|
|
15
|
+
static args: {
|
|
16
|
+
resource: import("@oclif/core/lib/interfaces").Arg<string, Record<string, unknown>>;
|
|
17
|
+
};
|
|
18
|
+
run(): Promise<void>;
|
|
19
|
+
}
|