ecomcoder-cli 1.2.15 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/test-utils.d.ts +123 -0
- package/dist/__tests__/test-utils.d.ts.map +1 -0
- package/dist/__tests__/test-utils.js +133 -0
- package/dist/__tests__/test-utils.js.map +1 -0
- package/dist/cli.d.ts +8 -7
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +70 -65
- package/dist/cli.js.map +1 -1
- package/dist/commands/docs/index.d.ts +10 -0
- package/dist/commands/docs/index.d.ts.map +1 -0
- package/dist/commands/docs/index.js +43 -0
- package/dist/commands/docs/index.js.map +1 -0
- package/dist/commands/metafield/index.d.ts +10 -0
- package/dist/commands/metafield/index.d.ts.map +1 -0
- package/dist/commands/metafield/index.js +55 -0
- package/dist/commands/metafield/index.js.map +1 -0
- package/dist/commands/product/__tests__/service.test.d.ts +7 -0
- package/dist/commands/product/__tests__/service.test.d.ts.map +1 -0
- package/dist/commands/product/__tests__/service.test.js +299 -0
- package/dist/commands/product/__tests__/service.test.js.map +1 -0
- package/dist/commands/product/__tests__/update-description.test.d.ts +5 -0
- package/dist/commands/product/__tests__/update-description.test.d.ts.map +1 -0
- package/dist/commands/product/__tests__/update-description.test.js +110 -0
- package/dist/commands/product/__tests__/update-description.test.js.map +1 -0
- package/dist/commands/product/get.d.ts +2 -0
- package/dist/commands/product/get.d.ts.map +1 -0
- package/dist/commands/product/get.js +305 -0
- package/dist/commands/product/get.js.map +1 -0
- package/dist/commands/product/index.d.ts +10 -0
- package/dist/commands/product/index.d.ts.map +1 -0
- package/dist/commands/product/index.js +73 -0
- package/dist/commands/product/index.js.map +1 -0
- package/dist/commands/product/queries.d.ts +32 -0
- package/dist/commands/product/queries.d.ts.map +1 -0
- package/dist/commands/product/queries.js +195 -0
- package/dist/commands/product/queries.js.map +1 -0
- package/dist/commands/product/service.d.ts +51 -0
- package/dist/commands/product/service.d.ts.map +1 -0
- package/dist/commands/product/service.js +237 -0
- package/dist/commands/product/service.js.map +1 -0
- package/dist/commands/product/types.d.ts +165 -0
- package/dist/commands/product/types.d.ts.map +1 -0
- package/dist/commands/product/types.js +6 -0
- package/dist/commands/product/types.js.map +1 -0
- package/dist/commands/product/update-description.d.ts +8 -0
- package/dist/commands/product/update-description.d.ts.map +1 -0
- package/dist/commands/product/update-description.js +86 -0
- package/dist/commands/product/update-description.js.map +1 -0
- package/dist/commands/product/update-price.d.ts +8 -0
- package/dist/commands/product/update-price.d.ts.map +1 -0
- package/dist/commands/product/update-price.js +101 -0
- package/dist/commands/product/update-price.js.map +1 -0
- package/dist/commands/product/update-template.d.ts +8 -0
- package/dist/commands/product/update-template.d.ts.map +1 -0
- package/dist/commands/product/update-template.js +114 -0
- package/dist/commands/product/update-template.js.map +1 -0
- package/dist/commands/product/utils.d.ts +69 -0
- package/dist/commands/product/utils.d.ts.map +1 -0
- package/dist/commands/product/utils.js +180 -0
- package/dist/commands/product/utils.js.map +1 -0
- package/dist/commands/products/index.d.ts +10 -0
- package/dist/commands/products/index.d.ts.map +1 -0
- package/dist/commands/products/index.js +62 -0
- package/dist/commands/products/index.js.map +1 -0
- package/dist/lib/api-client.d.ts.map +1 -1
- package/dist/lib/api-client.js +11 -0
- package/dist/lib/api-client.js.map +1 -1
- package/dist/lib/args-parser.d.ts.map +1 -1
- package/dist/lib/args-parser.js +2 -1
- package/dist/lib/args-parser.js.map +1 -1
- package/dist/lib/command-registry.d.ts +64 -0
- package/dist/lib/command-registry.d.ts.map +1 -0
- package/dist/lib/command-registry.js +76 -0
- package/dist/lib/command-registry.js.map +1 -0
- package/package.json +10 -2
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update Product Price Command
|
|
3
|
+
*
|
|
4
|
+
* Following Command Pattern - thin orchestration layer
|
|
5
|
+
* Delegates business logic to ProductService
|
|
6
|
+
*/
|
|
7
|
+
import { getCredentials, getSessionId } from '../../lib/api-client.js';
|
|
8
|
+
import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
|
|
9
|
+
import { ProductService } from './service.js';
|
|
10
|
+
function showHelp() {
|
|
11
|
+
console.log(`
|
|
12
|
+
Update Product Price
|
|
13
|
+
|
|
14
|
+
USAGE:
|
|
15
|
+
ecomcoder product update-price [OPTIONS]
|
|
16
|
+
|
|
17
|
+
OPTIONS:
|
|
18
|
+
--id <id> Product ID (required)
|
|
19
|
+
--price <amount> New price (required)
|
|
20
|
+
--variant-id <id> Specific variant ID (optional)
|
|
21
|
+
--all-variants Update ALL variants to the same price (optional)
|
|
22
|
+
--compare-at-price <amount> Compare at price / original price (optional)
|
|
23
|
+
--session-id Session ID (auto-provided via SESSION_ID env var)
|
|
24
|
+
--help, -h Show this help message
|
|
25
|
+
|
|
26
|
+
EXAMPLES:
|
|
27
|
+
# Update price of single-variant product
|
|
28
|
+
ecomcoder product update-price --id=123456789 --price=34.99
|
|
29
|
+
|
|
30
|
+
# Update ALL variants at once (efficient for multi-variant products)
|
|
31
|
+
ecomcoder product update-price --id=123 --price=29.99 --all-variants
|
|
32
|
+
|
|
33
|
+
# Add sale pricing to all variants
|
|
34
|
+
ecomcoder product update-price --id=123 --price=24.99 --compare-at-price=39.99 --all-variants
|
|
35
|
+
|
|
36
|
+
# Update specific variant
|
|
37
|
+
ecomcoder product update-price --id=123 --variant-id=456 --price=32.99
|
|
38
|
+
|
|
39
|
+
# Remove compare-at price from all variants
|
|
40
|
+
ecomcoder product update-price --id=123 --price=29.99 --compare-at-price="" --all-variants
|
|
41
|
+
|
|
42
|
+
NOTES:
|
|
43
|
+
- Uses Shopify's productVariantsBulkUpdate API (current standard)
|
|
44
|
+
- If product has multiple variants, use --all-variants or --variant-id
|
|
45
|
+
- --all-variants updates all variants in ONE API call (fast & efficient)
|
|
46
|
+
- Price must be a positive number with max 2 decimal places
|
|
47
|
+
- Compare-at price is optional and used for showing "was $X, now $Y"
|
|
48
|
+
- Empty compare-at price ("") will remove the sale pricing
|
|
49
|
+
|
|
50
|
+
API REFERENCE:
|
|
51
|
+
https://shopify.dev/docs/api/admin-graphql/latest/mutations/productvariantsbulkupdate
|
|
52
|
+
`);
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
export async function run(argv = process.argv.slice(2)) {
|
|
56
|
+
if (hasHelpFlag(argv)) {
|
|
57
|
+
showHelp();
|
|
58
|
+
}
|
|
59
|
+
const args = parseArgs(argv);
|
|
60
|
+
// Validate required arguments
|
|
61
|
+
if (!args.id) {
|
|
62
|
+
console.error(JSON.stringify({
|
|
63
|
+
success: false,
|
|
64
|
+
error: 'Missing required argument: --id'
|
|
65
|
+
}));
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
if (!args.price) {
|
|
69
|
+
console.error(JSON.stringify({
|
|
70
|
+
success: false,
|
|
71
|
+
error: 'Missing required argument: --price'
|
|
72
|
+
}));
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
try {
|
|
76
|
+
// Get credentials
|
|
77
|
+
const sessionId = getSessionId(args.sessionId);
|
|
78
|
+
const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
|
|
79
|
+
// Execute update via service
|
|
80
|
+
const result = await ProductService.updatePrice(credentials, {
|
|
81
|
+
id: args.id,
|
|
82
|
+
price: args.price,
|
|
83
|
+
variantId: args.variantId,
|
|
84
|
+
compareAtPrice: args.compareAtPrice,
|
|
85
|
+
allVariants: !!args.allVariants
|
|
86
|
+
});
|
|
87
|
+
// Output result
|
|
88
|
+
console.log(JSON.stringify(result));
|
|
89
|
+
if (!result.success) {
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
console.error(JSON.stringify({
|
|
95
|
+
success: false,
|
|
96
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
97
|
+
}));
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=update-price.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-price.js","sourceRoot":"","sources":["../../../src/commands/product/update-price.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAE9C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyCb,CAAC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE7B,8BAA8B;IAC9B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,iCAAiC;SACzC,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,oCAAoC;SAC5C,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,kBAAkB;QAClB,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAE/E,6BAA6B;QAC7B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,WAAW,CAAC,WAAW,EAAE;YAC3D,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW;SAChC,CAAC,CAAC;QAEH,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAEpC,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IAEH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAChE,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-template.d.ts","sourceRoot":"","sources":["../../../src/commands/product/update-template.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAsDH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAkE/D"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update Product Template Command
|
|
3
|
+
*
|
|
4
|
+
* Following Command Pattern - thin orchestration layer
|
|
5
|
+
* Delegates business logic to ProductService
|
|
6
|
+
*/
|
|
7
|
+
import { getCredentials, getSessionId } from '../../lib/api-client.js';
|
|
8
|
+
import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
|
|
9
|
+
import { ProductService } from './service.js';
|
|
10
|
+
function showHelp() {
|
|
11
|
+
console.log(`
|
|
12
|
+
Update Product Template Assignment
|
|
13
|
+
|
|
14
|
+
USAGE:
|
|
15
|
+
ecomcoder product update-template [OPTIONS]
|
|
16
|
+
|
|
17
|
+
OPTIONS:
|
|
18
|
+
--id <id> Product ID (required)
|
|
19
|
+
--template <name> Template name (required)
|
|
20
|
+
--session-id Session ID (auto-provided via SESSION_ID env var)
|
|
21
|
+
--help, -h Show this help message
|
|
22
|
+
|
|
23
|
+
EXAMPLES:
|
|
24
|
+
# Assign custom template
|
|
25
|
+
ecomcoder product update-template --id=123456789 --template=custom
|
|
26
|
+
|
|
27
|
+
# Same as above (handles "product." prefix automatically)
|
|
28
|
+
ecomcoder product update-template --id=123 --template=product.custom
|
|
29
|
+
|
|
30
|
+
# Reset to default template
|
|
31
|
+
ecomcoder product update-template --id=123 --template=default
|
|
32
|
+
|
|
33
|
+
# Assign premium template
|
|
34
|
+
ecomcoder product update-template --id=123 --template=premium
|
|
35
|
+
|
|
36
|
+
TEMPLATE NAMING:
|
|
37
|
+
- "default" → Uses templates/product.json
|
|
38
|
+
- "custom" → Uses templates/product.custom.json
|
|
39
|
+
- "product.custom" → Same as "custom" (prefix is stripped)
|
|
40
|
+
|
|
41
|
+
NOTES:
|
|
42
|
+
⚠️ IMPORTANT: Changing template is a BACKEND/CODE operation
|
|
43
|
+
- Template determines which page layout Shopify uses to render the product
|
|
44
|
+
- You must create the template file BEFORE assigning it to a product
|
|
45
|
+
- If template file doesn't exist, product page may not render correctly
|
|
46
|
+
|
|
47
|
+
WORKFLOW FOR NEW TEMPLATE:
|
|
48
|
+
1. Create template file: templates/product.premium.json
|
|
49
|
+
2. Design the layout (add sections, customize)
|
|
50
|
+
3. Assign to product: ecomcoder product update-template --id=123 --template=premium
|
|
51
|
+
|
|
52
|
+
This keeps the original template intact while giving specific products custom designs.
|
|
53
|
+
`);
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
export async function run(argv = process.argv.slice(2)) {
|
|
57
|
+
if (hasHelpFlag(argv)) {
|
|
58
|
+
showHelp();
|
|
59
|
+
}
|
|
60
|
+
const args = parseArgs(argv);
|
|
61
|
+
// Validate required arguments
|
|
62
|
+
if (!args.id) {
|
|
63
|
+
console.error(JSON.stringify({
|
|
64
|
+
success: false,
|
|
65
|
+
error: 'Missing required argument: --id'
|
|
66
|
+
}));
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (!args.template) {
|
|
70
|
+
console.error(JSON.stringify({
|
|
71
|
+
success: false,
|
|
72
|
+
error: 'Missing required argument: --template'
|
|
73
|
+
}));
|
|
74
|
+
process.exit(1);
|
|
75
|
+
}
|
|
76
|
+
try {
|
|
77
|
+
// Get credentials
|
|
78
|
+
const sessionId = getSessionId(args.sessionId);
|
|
79
|
+
const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
|
|
80
|
+
// Execute update via service
|
|
81
|
+
const result = await ProductService.updateTemplate(credentials, {
|
|
82
|
+
id: args.id,
|
|
83
|
+
template: args.template
|
|
84
|
+
});
|
|
85
|
+
// Add template file warning to successful response
|
|
86
|
+
let outputResult = result;
|
|
87
|
+
if (result.success && result.data) {
|
|
88
|
+
const templateName = result.data.product.template;
|
|
89
|
+
const templateFile = templateName === 'product'
|
|
90
|
+
? 'templates/product.json'
|
|
91
|
+
: `templates/${templateName}.json`;
|
|
92
|
+
outputResult = {
|
|
93
|
+
...result,
|
|
94
|
+
data: {
|
|
95
|
+
...result.data,
|
|
96
|
+
warning: `⚠️ Make sure the template file exists: ${templateFile}`
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
// Output result
|
|
101
|
+
console.log(JSON.stringify(outputResult));
|
|
102
|
+
if (!result.success) {
|
|
103
|
+
process.exit(1);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
console.error(JSON.stringify({
|
|
108
|
+
success: false,
|
|
109
|
+
error: error instanceof Error ? error.message : 'Unknown error'
|
|
110
|
+
}));
|
|
111
|
+
process.exit(1);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=update-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-template.js","sourceRoot":"","sources":["../../../src/commands/product/update-template.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAG9C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Cb,CAAC,CAAC;IACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,IAAI,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;QACtB,QAAQ,EAAE,CAAC;IACb,CAAC;IAED,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;IAE7B,8BAA8B;IAC9B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,iCAAiC;SACzC,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,uCAAuC;SAC/C,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,kBAAkB;QAClB,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/C,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;QAE/E,6BAA6B;QAC7B,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,cAAc,CAAC,WAAW,EAAE;YAC9D,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAC;QAEH,mDAAmD;QACnD,IAAI,YAAY,GAAG,MAAM,CAAC;QAC1B,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC;YAClC,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;YAClD,MAAM,YAAY,GAAG,YAAY,KAAK,SAAS;gBAC7C,CAAC,CAAC,wBAAwB;gBAC1B,CAAC,CAAC,aAAa,YAAY,OAAO,CAAC;YAErC,YAAY,GAAG;gBACb,GAAG,MAAM;gBACT,IAAI,EAAE;oBACJ,GAAG,MAAM,CAAC,IAAI;oBACd,OAAO,EAAE,2CAA2C,YAAY,EAAE;iBACnE;aACK,CAAC;QACX,CAAC;QAED,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;QAE1C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IAEH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe;SAChE,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Utilities
|
|
3
|
+
*
|
|
4
|
+
* Following Single Responsibility Principle - each function has one clear purpose
|
|
5
|
+
*/
|
|
6
|
+
import type { ShopifyProduct, FormattedProduct, NormalizedId, ShopifyUserError } from './types.js';
|
|
7
|
+
/**
|
|
8
|
+
* Normalize product ID to Shopify GID format
|
|
9
|
+
*
|
|
10
|
+
* Accepts:
|
|
11
|
+
* - Numeric ID: "123456789"
|
|
12
|
+
* - Full GID: "gid://shopify/Product/123456789"
|
|
13
|
+
*
|
|
14
|
+
* Returns both formats for flexibility
|
|
15
|
+
*/
|
|
16
|
+
export declare function normalizeProductId(id: string): NormalizedId;
|
|
17
|
+
/**
|
|
18
|
+
* Normalize variant ID to Shopify GID format
|
|
19
|
+
*/
|
|
20
|
+
export declare function normalizeVariantId(id: string): NormalizedId;
|
|
21
|
+
/**
|
|
22
|
+
* Normalize template name
|
|
23
|
+
*
|
|
24
|
+
* Handles:
|
|
25
|
+
* - "default" -> null (uses product.json)
|
|
26
|
+
* - "custom" -> "custom" (uses product.custom.json)
|
|
27
|
+
* - "product.custom" -> "custom" (removes prefix)
|
|
28
|
+
*/
|
|
29
|
+
export declare function normalizeTemplateName(template: string): string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Format template for display
|
|
32
|
+
*
|
|
33
|
+
* null -> "product"
|
|
34
|
+
* "custom" -> "product.custom"
|
|
35
|
+
*/
|
|
36
|
+
export declare function formatTemplateForDisplay(templateSuffix: string | null): string;
|
|
37
|
+
/**
|
|
38
|
+
* Format product data for CLI output
|
|
39
|
+
*
|
|
40
|
+
* Transforms Shopify GraphQL response to clean, user-friendly format
|
|
41
|
+
*/
|
|
42
|
+
export declare function formatProduct(product: ShopifyProduct): FormattedProduct;
|
|
43
|
+
/**
|
|
44
|
+
* Validate price format
|
|
45
|
+
*
|
|
46
|
+
* Returns true if price is valid (positive number with max 2 decimal places)
|
|
47
|
+
*/
|
|
48
|
+
export declare function isValidPrice(price: string): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Format Shopify user errors for display
|
|
51
|
+
*/
|
|
52
|
+
export declare function formatUserErrors(errors: ShopifyUserError[]): string;
|
|
53
|
+
/**
|
|
54
|
+
* Check if GraphQL response has errors
|
|
55
|
+
*/
|
|
56
|
+
export declare function hasGraphQLErrors(response: any): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Extract GraphQL error messages
|
|
59
|
+
*/
|
|
60
|
+
export declare function extractGraphQLErrors(response: any): string;
|
|
61
|
+
/**
|
|
62
|
+
* Validate product ID format
|
|
63
|
+
*/
|
|
64
|
+
export declare function isValidProductId(id: string): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Validate variant ID format
|
|
67
|
+
*/
|
|
68
|
+
export declare function isValidVariantId(id: string): boolean;
|
|
69
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/commands/product/utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,gBAAgB,EACjB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAa3D;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAa3D;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUrE;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAK9E;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG,gBAAgB,CAgCvE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAQnD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,gBAAgB,EAAE,GAAG,MAAM,CAOnE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,GAAG,OAAO,CAEvD;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,GAAG,GAAG,MAAM,CAQ1D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAYpD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAYpD"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Product Utilities
|
|
3
|
+
*
|
|
4
|
+
* Following Single Responsibility Principle - each function has one clear purpose
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Normalize product ID to Shopify GID format
|
|
8
|
+
*
|
|
9
|
+
* Accepts:
|
|
10
|
+
* - Numeric ID: "123456789"
|
|
11
|
+
* - Full GID: "gid://shopify/Product/123456789"
|
|
12
|
+
*
|
|
13
|
+
* Returns both formats for flexibility
|
|
14
|
+
*/
|
|
15
|
+
export function normalizeProductId(id) {
|
|
16
|
+
if (id.startsWith('gid://shopify/Product/')) {
|
|
17
|
+
const numeric = id.split('/').pop() || '';
|
|
18
|
+
return {
|
|
19
|
+
gid: id,
|
|
20
|
+
numeric
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
gid: `gid://shopify/Product/${id}`,
|
|
25
|
+
numeric: id
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Normalize variant ID to Shopify GID format
|
|
30
|
+
*/
|
|
31
|
+
export function normalizeVariantId(id) {
|
|
32
|
+
if (id.startsWith('gid://shopify/ProductVariant/')) {
|
|
33
|
+
const numeric = id.split('/').pop() || '';
|
|
34
|
+
return {
|
|
35
|
+
gid: id,
|
|
36
|
+
numeric
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
gid: `gid://shopify/ProductVariant/${id}`,
|
|
41
|
+
numeric: id
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Normalize template name
|
|
46
|
+
*
|
|
47
|
+
* Handles:
|
|
48
|
+
* - "default" -> null (uses product.json)
|
|
49
|
+
* - "custom" -> "custom" (uses product.custom.json)
|
|
50
|
+
* - "product.custom" -> "custom" (removes prefix)
|
|
51
|
+
*/
|
|
52
|
+
export function normalizeTemplateName(template) {
|
|
53
|
+
if (template === 'default') {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
if (template.startsWith('product.')) {
|
|
57
|
+
return template.replace('product.', '');
|
|
58
|
+
}
|
|
59
|
+
return template;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Format template for display
|
|
63
|
+
*
|
|
64
|
+
* null -> "product"
|
|
65
|
+
* "custom" -> "product.custom"
|
|
66
|
+
*/
|
|
67
|
+
export function formatTemplateForDisplay(templateSuffix) {
|
|
68
|
+
if (!templateSuffix) {
|
|
69
|
+
return 'product';
|
|
70
|
+
}
|
|
71
|
+
return `product.${templateSuffix}`;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Format product data for CLI output
|
|
75
|
+
*
|
|
76
|
+
* Transforms Shopify GraphQL response to clean, user-friendly format
|
|
77
|
+
*/
|
|
78
|
+
export function formatProduct(product) {
|
|
79
|
+
return {
|
|
80
|
+
id: product.id,
|
|
81
|
+
title: product.title,
|
|
82
|
+
description: product.description,
|
|
83
|
+
handle: product.handle,
|
|
84
|
+
status: product.status,
|
|
85
|
+
productType: product.productType,
|
|
86
|
+
vendor: product.vendor,
|
|
87
|
+
template: formatTemplateForDisplay(product.templateSuffix),
|
|
88
|
+
tags: product.tags,
|
|
89
|
+
priceRange: {
|
|
90
|
+
min: product.priceRangeV2.minVariantPrice,
|
|
91
|
+
max: product.priceRangeV2.maxVariantPrice
|
|
92
|
+
},
|
|
93
|
+
variants: product.variants.edges.map(e => ({
|
|
94
|
+
id: e.node.id,
|
|
95
|
+
title: e.node.title,
|
|
96
|
+
price: e.node.price,
|
|
97
|
+
compareAtPrice: e.node.compareAtPrice,
|
|
98
|
+
sku: e.node.sku,
|
|
99
|
+
inventory: e.node.inventoryQuantity,
|
|
100
|
+
available: e.node.availableForSale
|
|
101
|
+
})),
|
|
102
|
+
images: product.images.edges.map(e => ({
|
|
103
|
+
id: e.node.id,
|
|
104
|
+
url: e.node.url,
|
|
105
|
+
altText: e.node.altText,
|
|
106
|
+
width: e.node.width,
|
|
107
|
+
height: e.node.height
|
|
108
|
+
}))
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Validate price format
|
|
113
|
+
*
|
|
114
|
+
* Returns true if price is valid (positive number with max 2 decimal places)
|
|
115
|
+
*/
|
|
116
|
+
export function isValidPrice(price) {
|
|
117
|
+
const priceRegex = /^\d+(\.\d{1,2})?$/;
|
|
118
|
+
if (!priceRegex.test(price)) {
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
const numPrice = parseFloat(price);
|
|
122
|
+
return numPrice > 0;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Format Shopify user errors for display
|
|
126
|
+
*/
|
|
127
|
+
export function formatUserErrors(errors) {
|
|
128
|
+
return errors
|
|
129
|
+
.map(err => {
|
|
130
|
+
const field = err.field ? err.field.join('.') : 'unknown';
|
|
131
|
+
return `${field}: ${err.message}`;
|
|
132
|
+
})
|
|
133
|
+
.join('\n');
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Check if GraphQL response has errors
|
|
137
|
+
*/
|
|
138
|
+
export function hasGraphQLErrors(response) {
|
|
139
|
+
return response.errors && response.errors.length > 0;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Extract GraphQL error messages
|
|
143
|
+
*/
|
|
144
|
+
export function extractGraphQLErrors(response) {
|
|
145
|
+
if (!hasGraphQLErrors(response)) {
|
|
146
|
+
return '';
|
|
147
|
+
}
|
|
148
|
+
return response.errors
|
|
149
|
+
.map((e) => e.message)
|
|
150
|
+
.join(', ');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Validate product ID format
|
|
154
|
+
*/
|
|
155
|
+
export function isValidProductId(id) {
|
|
156
|
+
// Accept numeric ID or full GID
|
|
157
|
+
if (/^\d+$/.test(id)) {
|
|
158
|
+
return true;
|
|
159
|
+
}
|
|
160
|
+
if (id.startsWith('gid://shopify/Product/')) {
|
|
161
|
+
const numeric = id.split('/').pop();
|
|
162
|
+
return !!numeric && /^\d+$/.test(numeric);
|
|
163
|
+
}
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Validate variant ID format
|
|
168
|
+
*/
|
|
169
|
+
export function isValidVariantId(id) {
|
|
170
|
+
// Accept numeric ID or full GID
|
|
171
|
+
if (/^\d+$/.test(id)) {
|
|
172
|
+
return true;
|
|
173
|
+
}
|
|
174
|
+
if (id.startsWith('gid://shopify/ProductVariant/')) {
|
|
175
|
+
const numeric = id.split('/').pop();
|
|
176
|
+
return !!numeric && /^\d+$/.test(numeric);
|
|
177
|
+
}
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/product/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/products/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAsD/C"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Products Commands Registration
|
|
3
|
+
*
|
|
4
|
+
* Following Open/Closed Principle - commands register themselves
|
|
5
|
+
*/
|
|
6
|
+
import { registry } from '../../lib/command-registry.js';
|
|
7
|
+
/**
|
|
8
|
+
* Register all products commands
|
|
9
|
+
*/
|
|
10
|
+
export function registerProductsCommands() {
|
|
11
|
+
// Register command group
|
|
12
|
+
registry.registerGroup({
|
|
13
|
+
command: 'products',
|
|
14
|
+
description: 'Manage multiple Shopify products (bulk operations)',
|
|
15
|
+
showHelp: () => {
|
|
16
|
+
console.log(`
|
|
17
|
+
Products Commands - Bulk product operations and utilities
|
|
18
|
+
|
|
19
|
+
USAGE:
|
|
20
|
+
ecomcoder products <subcommand> [options]
|
|
21
|
+
|
|
22
|
+
SUBCOMMANDS:
|
|
23
|
+
create Create dummy Shopify products for testing
|
|
24
|
+
list List products in your Shopify store
|
|
25
|
+
set-rating Set rating metafields on a product
|
|
26
|
+
|
|
27
|
+
EXAMPLES:
|
|
28
|
+
# Create 10 dummy products
|
|
29
|
+
ecomcoder products create --count=10
|
|
30
|
+
|
|
31
|
+
# List 50 products
|
|
32
|
+
ecomcoder products list --limit=50
|
|
33
|
+
|
|
34
|
+
# Set product rating
|
|
35
|
+
ecomcoder products set-rating --product-id="gid://shopify/Product/123" --rating=4.5 --count=127
|
|
36
|
+
|
|
37
|
+
For detailed help on a specific subcommand:
|
|
38
|
+
ecomcoder products <subcommand> --help
|
|
39
|
+
`);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
// Register individual subcommands
|
|
43
|
+
registry.register({
|
|
44
|
+
command: 'products',
|
|
45
|
+
subcommand: 'create',
|
|
46
|
+
description: 'Create dummy Shopify products for testing',
|
|
47
|
+
handler: async () => await import('../create-dummy-products.js')
|
|
48
|
+
});
|
|
49
|
+
registry.register({
|
|
50
|
+
command: 'products',
|
|
51
|
+
subcommand: 'list',
|
|
52
|
+
description: 'List products in your Shopify store',
|
|
53
|
+
handler: async () => await import('../list-products.js')
|
|
54
|
+
});
|
|
55
|
+
registry.register({
|
|
56
|
+
command: 'products',
|
|
57
|
+
subcommand: 'set-rating',
|
|
58
|
+
description: 'Set rating metafields on a product',
|
|
59
|
+
handler: async () => await import('../set-product-rating.js')
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/products/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAEzD;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,yBAAyB;IACzB,QAAQ,CAAC,aAAa,CAAC;QACrB,OAAO,EAAE,UAAU;QACnB,WAAW,EAAE,oDAAoD;QACjE,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;CAuBjB,CAAC,CAAC;QACC,CAAC;KACF,CAAC,CAAC;IAEH,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,2CAA2C;QACxD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,6BAA6B,CAAC;KACjE,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,qCAAqC;QAClD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,qBAAqB,CAAC;KACzD,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,YAAY;QACxB,WAAW,EAAE,oCAAoC;QACjD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,0BAA0B,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,CAAC,
|
|
1
|
+
{"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;GAOG;AACH,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,kBAAkB,CAAC,EAAE,MAAM,EAC3B,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAAC,kBAAkB,CAAC,CAiD7B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAa/D;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBrG"}
|
package/dist/lib/api-client.js
CHANGED
|
@@ -11,6 +11,13 @@
|
|
|
11
11
|
* Can be overridden with explicit parameters for testing
|
|
12
12
|
*/
|
|
13
13
|
export async function getCredentials(sessionId, backendUrlOverride, jwtOverride) {
|
|
14
|
+
// Support direct credentials for testing (bypass backend)
|
|
15
|
+
if (process.env.SHOPIFY_URL && process.env.SHOPIFY_ADMIN_PASSWORD) {
|
|
16
|
+
return {
|
|
17
|
+
shopifyUrl: process.env.SHOPIFY_URL,
|
|
18
|
+
shopifyAdminPassword: process.env.SHOPIFY_ADMIN_PASSWORD
|
|
19
|
+
};
|
|
20
|
+
}
|
|
14
21
|
const backendURL = backendUrlOverride || process.env.BACKEND_URL;
|
|
15
22
|
const jwt = jwtOverride || process.env.SUPABASE_JWT;
|
|
16
23
|
if (!backendURL) {
|
|
@@ -51,6 +58,10 @@ export async function getCredentials(sessionId, backendUrlOverride, jwtOverride)
|
|
|
51
58
|
*/
|
|
52
59
|
export function getSessionId(explicitSessionId) {
|
|
53
60
|
const sessionId = explicitSessionId || process.env.SESSION_ID;
|
|
61
|
+
// Allow bypass for direct credential testing
|
|
62
|
+
if (!sessionId && process.env.SHOPIFY_URL && process.env.SHOPIFY_ADMIN_PASSWORD) {
|
|
63
|
+
return 'test-mode';
|
|
64
|
+
}
|
|
54
65
|
if (!sessionId) {
|
|
55
66
|
throw new Error('Session ID is required. Provide --session-id flag or set SESSION_ID environment variable.');
|
|
56
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api-client.js","sourceRoot":"","sources":["../../src/lib/api-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args-parser.d.ts","sourceRoot":"","sources":["../../src/lib/args-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"args-parser.d.ts","sourceRoot":"","sources":["../../src/lib/args-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AACH,wBAAgB,SAAS,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAaxF;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAElE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,GAAE,MAAM,EAA0B,GAAG,MAAM,EAAE,CAElF"}
|
package/dist/lib/args-parser.js
CHANGED
|
@@ -15,7 +15,8 @@ export function parseArgs(argv = process.argv.slice(2)) {
|
|
|
15
15
|
if (arg.startsWith('--')) {
|
|
16
16
|
const [key, value] = arg.slice(2).split('=');
|
|
17
17
|
const camelKey = key.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
18
|
-
|
|
18
|
+
// Allow empty strings (don't default to 'true' for values like --description="")
|
|
19
|
+
args[camelKey] = value !== undefined ? value : 'true';
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
22
|
return args;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args-parser.js","sourceRoot":"","sources":["../../src/lib/args-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAA2B,EAAE,CAAC;IAExC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC/E,IAAI,CAAC,QAAQ,CAAC,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"args-parser.js","sourceRoot":"","sources":["../../src/lib/args-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAA2B,EAAE,CAAC;IAExC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC/E,iFAAiF;YACjF,IAAI,CAAC,QAAQ,CAAC,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACxD,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAiB,OAAO,CAAC,IAAI;IACvD,OAAO,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IACtE,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3E,CAAC"}
|