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.
Files changed (75) hide show
  1. package/dist/__tests__/test-utils.d.ts +123 -0
  2. package/dist/__tests__/test-utils.d.ts.map +1 -0
  3. package/dist/__tests__/test-utils.js +133 -0
  4. package/dist/__tests__/test-utils.js.map +1 -0
  5. package/dist/cli.d.ts +8 -7
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +70 -65
  8. package/dist/cli.js.map +1 -1
  9. package/dist/commands/docs/index.d.ts +10 -0
  10. package/dist/commands/docs/index.d.ts.map +1 -0
  11. package/dist/commands/docs/index.js +43 -0
  12. package/dist/commands/docs/index.js.map +1 -0
  13. package/dist/commands/metafield/index.d.ts +10 -0
  14. package/dist/commands/metafield/index.d.ts.map +1 -0
  15. package/dist/commands/metafield/index.js +55 -0
  16. package/dist/commands/metafield/index.js.map +1 -0
  17. package/dist/commands/product/__tests__/service.test.d.ts +7 -0
  18. package/dist/commands/product/__tests__/service.test.d.ts.map +1 -0
  19. package/dist/commands/product/__tests__/service.test.js +299 -0
  20. package/dist/commands/product/__tests__/service.test.js.map +1 -0
  21. package/dist/commands/product/__tests__/update-description.test.d.ts +5 -0
  22. package/dist/commands/product/__tests__/update-description.test.d.ts.map +1 -0
  23. package/dist/commands/product/__tests__/update-description.test.js +110 -0
  24. package/dist/commands/product/__tests__/update-description.test.js.map +1 -0
  25. package/dist/commands/product/get.d.ts +2 -0
  26. package/dist/commands/product/get.d.ts.map +1 -0
  27. package/dist/commands/product/get.js +305 -0
  28. package/dist/commands/product/get.js.map +1 -0
  29. package/dist/commands/product/index.d.ts +10 -0
  30. package/dist/commands/product/index.d.ts.map +1 -0
  31. package/dist/commands/product/index.js +73 -0
  32. package/dist/commands/product/index.js.map +1 -0
  33. package/dist/commands/product/queries.d.ts +32 -0
  34. package/dist/commands/product/queries.d.ts.map +1 -0
  35. package/dist/commands/product/queries.js +195 -0
  36. package/dist/commands/product/queries.js.map +1 -0
  37. package/dist/commands/product/service.d.ts +51 -0
  38. package/dist/commands/product/service.d.ts.map +1 -0
  39. package/dist/commands/product/service.js +237 -0
  40. package/dist/commands/product/service.js.map +1 -0
  41. package/dist/commands/product/types.d.ts +165 -0
  42. package/dist/commands/product/types.d.ts.map +1 -0
  43. package/dist/commands/product/types.js +6 -0
  44. package/dist/commands/product/types.js.map +1 -0
  45. package/dist/commands/product/update-description.d.ts +8 -0
  46. package/dist/commands/product/update-description.d.ts.map +1 -0
  47. package/dist/commands/product/update-description.js +86 -0
  48. package/dist/commands/product/update-description.js.map +1 -0
  49. package/dist/commands/product/update-price.d.ts +8 -0
  50. package/dist/commands/product/update-price.d.ts.map +1 -0
  51. package/dist/commands/product/update-price.js +101 -0
  52. package/dist/commands/product/update-price.js.map +1 -0
  53. package/dist/commands/product/update-template.d.ts +8 -0
  54. package/dist/commands/product/update-template.d.ts.map +1 -0
  55. package/dist/commands/product/update-template.js +114 -0
  56. package/dist/commands/product/update-template.js.map +1 -0
  57. package/dist/commands/product/utils.d.ts +69 -0
  58. package/dist/commands/product/utils.d.ts.map +1 -0
  59. package/dist/commands/product/utils.js +180 -0
  60. package/dist/commands/product/utils.js.map +1 -0
  61. package/dist/commands/products/index.d.ts +10 -0
  62. package/dist/commands/products/index.d.ts.map +1 -0
  63. package/dist/commands/products/index.js +62 -0
  64. package/dist/commands/products/index.js.map +1 -0
  65. package/dist/lib/api-client.d.ts.map +1 -1
  66. package/dist/lib/api-client.js +11 -0
  67. package/dist/lib/api-client.js.map +1 -1
  68. package/dist/lib/args-parser.d.ts.map +1 -1
  69. package/dist/lib/args-parser.js +2 -1
  70. package/dist/lib/args-parser.js.map +1 -1
  71. package/dist/lib/command-registry.d.ts +64 -0
  72. package/dist/lib/command-registry.d.ts.map +1 -0
  73. package/dist/lib/command-registry.js +76 -0
  74. package/dist/lib/command-registry.js.map +1 -0
  75. 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,8 @@
1
+ /**
2
+ * Update Product Template Command
3
+ *
4
+ * Following Command Pattern - thin orchestration layer
5
+ * Delegates business logic to ProductService
6
+ */
7
+ export declare function run(argv?: string[]): Promise<void>;
8
+ //# sourceMappingURL=update-template.d.ts.map
@@ -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":"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"}
@@ -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,10 @@
1
+ /**
2
+ * Products Commands Registration
3
+ *
4
+ * Following Open/Closed Principle - commands register themselves
5
+ */
6
+ /**
7
+ * Register all products commands
8
+ */
9
+ export declare function registerProductsCommands(): void;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -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,CAyC7B;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ/D;AAED;;;GAGG;AACH,wBAAsB,sBAAsB,CAAC,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBrG"}
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"}
@@ -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,CAYxF;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"}
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"}
@@ -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
- args[camelKey] = value || 'true';
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,IAAI,MAAM,CAAC;QACnC,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"}
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"}