ecomcoder-cli 1.3.3 → 1.3.5

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 (80) hide show
  1. package/README.md +0 -23
  2. package/dist/cli.js +4 -84
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/discount/index.d.ts.map +1 -1
  5. package/dist/commands/discount/index.js +10 -49
  6. package/dist/commands/discount/index.js.map +1 -1
  7. package/dist/commands/docs/index.d.ts.map +1 -1
  8. package/dist/commands/docs/index.js +4 -18
  9. package/dist/commands/docs/index.js.map +1 -1
  10. package/dist/commands/metafield/index.d.ts.map +1 -1
  11. package/dist/commands/metafield/index.js +6 -24
  12. package/dist/commands/metafield/index.js.map +1 -1
  13. package/dist/commands/product/create.d.ts +8 -0
  14. package/dist/commands/product/create.d.ts.map +1 -0
  15. package/dist/commands/product/create.js +166 -0
  16. package/dist/commands/product/create.js.map +1 -0
  17. package/dist/commands/product/get-metafield.d.ts +8 -0
  18. package/dist/commands/product/get-metafield.d.ts.map +1 -0
  19. package/dist/commands/product/get-metafield.js +131 -0
  20. package/dist/commands/product/get-metafield.js.map +1 -0
  21. package/dist/commands/product/index.d.ts.map +1 -1
  22. package/dist/commands/product/index.js +42 -42
  23. package/dist/commands/product/index.js.map +1 -1
  24. package/dist/commands/product/queries.d.ts +19 -0
  25. package/dist/commands/product/queries.d.ts.map +1 -1
  26. package/dist/commands/product/queries.js +122 -0
  27. package/dist/commands/product/queries.js.map +1 -1
  28. package/dist/commands/product/service.d.ts +35 -1
  29. package/dist/commands/product/service.d.ts.map +1 -1
  30. package/dist/commands/product/service.js +241 -1
  31. package/dist/commands/product/service.js.map +1 -1
  32. package/dist/commands/product/set-metafield.d.ts +8 -0
  33. package/dist/commands/product/set-metafield.d.ts.map +1 -0
  34. package/dist/commands/product/set-metafield.js +174 -0
  35. package/dist/commands/product/set-metafield.js.map +1 -0
  36. package/dist/commands/product/types.d.ts +88 -0
  37. package/dist/commands/product/types.d.ts.map +1 -1
  38. package/dist/commands/product/update-status.d.ts +8 -0
  39. package/dist/commands/product/update-status.d.ts.map +1 -0
  40. package/dist/commands/product/update-status.js +105 -0
  41. package/dist/commands/product/update-status.js.map +1 -0
  42. package/dist/commands/products/index.d.ts.map +1 -1
  43. package/dist/commands/products/index.js +5 -31
  44. package/dist/commands/products/index.js.map +1 -1
  45. package/dist/commands/shop/get-metafield.d.ts +8 -0
  46. package/dist/commands/shop/get-metafield.d.ts.map +1 -0
  47. package/dist/commands/shop/get-metafield.js +117 -0
  48. package/dist/commands/shop/get-metafield.js.map +1 -0
  49. package/dist/commands/shop/index.d.ts +10 -0
  50. package/dist/commands/shop/index.d.ts.map +1 -0
  51. package/dist/commands/shop/index.js +38 -0
  52. package/dist/commands/shop/index.js.map +1 -0
  53. package/dist/commands/shop/queries.d.ts +24 -0
  54. package/dist/commands/shop/queries.d.ts.map +1 -0
  55. package/dist/commands/shop/queries.js +83 -0
  56. package/dist/commands/shop/queries.js.map +1 -0
  57. package/dist/commands/shop/service.d.ts +30 -0
  58. package/dist/commands/shop/service.d.ts.map +1 -0
  59. package/dist/commands/shop/service.js +131 -0
  60. package/dist/commands/shop/service.js.map +1 -0
  61. package/dist/commands/shop/set-metafield.d.ts +8 -0
  62. package/dist/commands/shop/set-metafield.d.ts.map +1 -0
  63. package/dist/commands/shop/set-metafield.js +174 -0
  64. package/dist/commands/shop/set-metafield.js.map +1 -0
  65. package/dist/commands/shop/types.d.ts +84 -0
  66. package/dist/commands/shop/types.d.ts.map +1 -0
  67. package/dist/commands/shop/types.js +6 -0
  68. package/dist/commands/shop/types.js.map +1 -0
  69. package/dist/lib/command-registry.d.ts +2 -0
  70. package/dist/lib/command-registry.d.ts.map +1 -1
  71. package/dist/lib/command-registry.js.map +1 -1
  72. package/dist/lib/help-generator.d.ts +28 -0
  73. package/dist/lib/help-generator.d.ts.map +1 -0
  74. package/dist/lib/help-generator.js +131 -0
  75. package/dist/lib/help-generator.js.map +1 -0
  76. package/dist/lib/help-utils.d.ts +17 -0
  77. package/dist/lib/help-utils.d.ts.map +1 -0
  78. package/dist/lib/help-utils.js +24 -0
  79. package/dist/lib/help-utils.js.map +1 -0
  80. package/package.json +1 -1
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Update Product Status 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 Status
13
+
14
+ USAGE:
15
+ ecomcoder product update-status [OPTIONS]
16
+
17
+ REQUIRED OPTIONS:
18
+ --id <id> Product ID (numeric or GID)
19
+ --status <status> Product status: ACTIVE, DRAFT, ARCHIVED, or UNLISTED
20
+
21
+ OPTIONAL:
22
+ --session-id Session ID (auto-provided via SESSION_ID env var)
23
+ --help, -h Show this help message
24
+
25
+ STATUS VALUES:
26
+ ACTIVE Product is ready to sell (can be published to channels)
27
+ DRAFT Product not ready to sell (hidden from customers)
28
+ ARCHIVED Product no longer sold (hidden from customers)
29
+ UNLISTED Active but requires direct link (no search/collections)
30
+
31
+ EXAMPLES:
32
+ # Publish product (make it active)
33
+ ecomcoder product update-status --id=123456789 --status=ACTIVE
34
+
35
+ # Set to draft (hide from customers)
36
+ ecomcoder product update-status --id=123 --status=DRAFT
37
+
38
+ # Archive product (no longer sold)
39
+ ecomcoder product update-status --id=123 --status=ARCHIVED
40
+
41
+ # Unlisted (active but requires direct link)
42
+ ecomcoder product update-status --id=123 --status=UNLISTED
43
+
44
+ NOTES:
45
+ - Status change is immediate
46
+ - ACTIVE status does NOT automatically publish to channels
47
+ - Use Shopify Admin to manage channel publishing separately
48
+ - UNLISTED is available in API version 2025-10 and later
49
+ `);
50
+ process.exit(0);
51
+ }
52
+ export async function run(argv = process.argv.slice(2)) {
53
+ if (hasHelpFlag(argv)) {
54
+ showHelp();
55
+ }
56
+ const args = parseArgs(argv);
57
+ // Validate required arguments
58
+ if (!args.id) {
59
+ console.error(JSON.stringify({
60
+ success: false,
61
+ error: 'Missing required argument: --id'
62
+ }));
63
+ process.exit(1);
64
+ }
65
+ if (!args.status) {
66
+ console.error(JSON.stringify({
67
+ success: false,
68
+ error: 'Missing required argument: --status'
69
+ }));
70
+ process.exit(1);
71
+ }
72
+ // Validate status value
73
+ const validStatuses = ['ACTIVE', 'DRAFT', 'ARCHIVED', 'UNLISTED'];
74
+ const statusUpper = args.status.toUpperCase();
75
+ if (!validStatuses.includes(statusUpper)) {
76
+ console.error(JSON.stringify({
77
+ success: false,
78
+ error: `Invalid status. Must be one of: ${validStatuses.join(', ')}`
79
+ }));
80
+ process.exit(1);
81
+ }
82
+ try {
83
+ // Get credentials
84
+ const sessionId = getSessionId(args.sessionId);
85
+ const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
86
+ // Execute update via service
87
+ const result = await ProductService.updateStatus(credentials, {
88
+ id: args.id,
89
+ status: statusUpper
90
+ });
91
+ // Output result
92
+ console.log(JSON.stringify(result, null, 2));
93
+ if (!result.success) {
94
+ process.exit(1);
95
+ }
96
+ }
97
+ catch (error) {
98
+ console.error(JSON.stringify({
99
+ success: false,
100
+ error: error.message || 'Unknown error occurred'
101
+ }));
102
+ process.exit(1);
103
+ }
104
+ }
105
+ //# sourceMappingURL=update-status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-status.js","sourceRoot":"","sources":["../../../src/commands/product/update-status.ts"],"names":[],"mappings":"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"}
@@ -1 +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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/products/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;GAEG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CA0B/C"}
@@ -4,6 +4,7 @@
4
4
  * Following Open/Closed Principle - commands register themselves
5
5
  */
6
6
  import { registry } from '../../lib/command-registry.js';
7
+ import { HelpGenerator } from '../../lib/help-generator.js';
7
8
  /**
8
9
  * Register all products commands
9
10
  */
@@ -11,32 +12,9 @@ export function registerProductsCommands() {
11
12
  // Register command group
12
13
  registry.registerGroup({
13
14
  command: 'products',
14
- description: 'Manage multiple Shopify products (bulk operations)',
15
+ description: 'Bulk product operations',
15
16
  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
- `);
17
+ console.log(HelpGenerator.generateGroupHelp('products'));
40
18
  }
41
19
  });
42
20
  // Register individual subcommands
@@ -44,19 +22,15 @@ For detailed help on a specific subcommand:
44
22
  command: 'products',
45
23
  subcommand: 'create',
46
24
  description: 'Create dummy Shopify products for testing',
25
+ quickExample: 'ecomcoder products create --count=10',
47
26
  handler: async () => await import('../create-dummy-products.js')
48
27
  });
49
28
  registry.register({
50
29
  command: 'products',
51
30
  subcommand: 'list',
52
31
  description: 'List products in your Shopify store',
32
+ quickExample: 'ecomcoder products list --limit=50',
53
33
  handler: async () => await import('../list-products.js')
54
34
  });
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
35
  }
62
36
  //# sourceMappingURL=index.js.map
@@ -1 +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
+ {"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;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D;;GAEG;AACH,MAAM,UAAU,wBAAwB;IACtC,yBAAyB;IACzB,QAAQ,CAAC,aAAa,CAAC;QACrB,OAAO,EAAE,UAAU;QACnB,WAAW,EAAE,yBAAyB;QACtC,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,CAAC;QAC3D,CAAC;KACF,CAAC,CAAC;IAEH,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,UAAU;QACnB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,2CAA2C;QACxD,YAAY,EAAE,sCAAsC;QACpD,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,YAAY,EAAE,oCAAoC;QAClD,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,qBAAqB,CAAC;KACzD,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Get Shop Metafield Command
3
+ *
4
+ * Following Command Pattern - thin orchestration layer
5
+ * Delegates business logic to ShopService
6
+ */
7
+ export declare function run(argv?: string[]): Promise<void>;
8
+ //# sourceMappingURL=get-metafield.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-metafield.d.ts","sourceRoot":"","sources":["../../../src/commands/shop/get-metafield.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AA8EH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAwC/D"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * Get Shop Metafield Command
3
+ *
4
+ * Following Command Pattern - thin orchestration layer
5
+ * Delegates business logic to ShopService
6
+ */
7
+ import { getCredentials, getSessionId } from '../../lib/api-client.js';
8
+ import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
9
+ import { ShopService } from './service.js';
10
+ function showHelp() {
11
+ console.log(`
12
+ Get Shop Metafield
13
+
14
+ USAGE:
15
+ ecomcoder shop get-metafield [OPTIONS]
16
+
17
+ QUERY OPTIONS (choose one):
18
+ --namespace <ns> --key <key> Get specific metafield
19
+ --namespace <ns> Get all metafields in namespace
20
+ (no namespace/key) Get all metafields for shop
21
+
22
+ OPTIONAL:
23
+ --session-id Session ID (auto-provided via SESSION_ID env var)
24
+ --help, -h Show this help message
25
+
26
+ EXAMPLES:
27
+ # Get specific metafield by namespace and key
28
+ ecomcoder shop get-metafield \\
29
+ --namespace=custom \\
30
+ --key=announcement
31
+
32
+ # Get all metafields in a namespace
33
+ ecomcoder shop get-metafield \\
34
+ --namespace=custom
35
+
36
+ # Get all metafields for shop (all namespaces)
37
+ ecomcoder shop get-metafield
38
+
39
+ OUTPUT FORMATS:
40
+ Specific metafield (namespace + key):
41
+ {
42
+ "success": true,
43
+ "data": {
44
+ "metafield": {
45
+ "id": "gid://shopify/Metafield/123",
46
+ "namespace": "custom",
47
+ "key": "announcement",
48
+ "value": "Black Friday Sale!",
49
+ "type": "single_line_text_field",
50
+ "createdAt": "2024-01-20T10:30:00Z",
51
+ "updatedAt": "2024-01-20T15:45:00Z"
52
+ }
53
+ }
54
+ }
55
+
56
+ Multiple metafields (namespace or all):
57
+ {
58
+ "success": true,
59
+ "data": {
60
+ "metafields": [...],
61
+ "count": 5
62
+ }
63
+ }
64
+
65
+ Not found:
66
+ {
67
+ "success": true,
68
+ "data": {
69
+ "metafield": null
70
+ }
71
+ }
72
+
73
+ NOTES:
74
+ - Returns up to 250 metafields when querying multiple
75
+ - Namespace filter is optional (omit to get all namespaces)
76
+ - Key requires namespace (cannot query by key alone)
77
+ - Metafield values are always strings (parse JSON for complex types)
78
+ `);
79
+ process.exit(0);
80
+ }
81
+ export async function run(argv = process.argv.slice(2)) {
82
+ if (hasHelpFlag(argv)) {
83
+ showHelp();
84
+ }
85
+ const args = parseArgs(argv);
86
+ // Validate key requires namespace
87
+ if (args.key && !args.namespace) {
88
+ console.error(JSON.stringify({
89
+ success: false,
90
+ error: 'Key requires namespace. Use --namespace with --key'
91
+ }));
92
+ process.exit(1);
93
+ }
94
+ try {
95
+ // Get credentials
96
+ const sessionId = getSessionId(args.sessionId);
97
+ const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
98
+ // Execute get metafield via service
99
+ const result = await ShopService.getMetafield(credentials, {
100
+ namespace: args.namespace,
101
+ key: args.key
102
+ });
103
+ // Output result
104
+ console.log(JSON.stringify(result, null, 2));
105
+ if (!result.success) {
106
+ process.exit(1);
107
+ }
108
+ }
109
+ catch (error) {
110
+ console.error(JSON.stringify({
111
+ success: false,
112
+ error: error.message || 'Unknown error occurred'
113
+ }));
114
+ process.exit(1);
115
+ }
116
+ }
117
+ //# sourceMappingURL=get-metafield.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-metafield.js","sourceRoot":"","sources":["../../../src/commands/shop/get-metafield.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,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmEb,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,kCAAkC;IAClC,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAChC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,oDAAoD;SAC5D,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,oCAAoC;QACpC,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,YAAY,CAAC,WAAW,EAAE;YACzD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAC;QAEH,gBAAgB;QAChB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7C,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,KAAK,CAAC,OAAO,IAAI,wBAAwB;SACjD,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * Shop Commands Registration
3
+ *
4
+ * Following Open/Closed Principle - commands register themselves
5
+ */
6
+ /**
7
+ * Register all shop commands
8
+ */
9
+ export declare function registerShopCommands(): void;
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/shop/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH;;GAEG;AACH,wBAAgB,oBAAoB,IAAI,IAAI,CA4B3C"}
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Shop Commands Registration
3
+ *
4
+ * Following Open/Closed Principle - commands register themselves
5
+ */
6
+ import { registry } from '../../lib/command-registry.js';
7
+ import { HelpGenerator } from '../../lib/help-generator.js';
8
+ /**
9
+ * Register all shop commands
10
+ */
11
+ export function registerShopCommands() {
12
+ // Register command group
13
+ registry.registerGroup({
14
+ command: 'shop',
15
+ description: 'Store-wide settings and metafields',
16
+ showHelp: () => {
17
+ console.log(HelpGenerator.generateGroupHelp('shop'));
18
+ }
19
+ });
20
+ // Register individual subcommands
21
+ registry.register({
22
+ command: 'shop',
23
+ subcommand: 'set-metafield',
24
+ description: 'Set or update shop metafield values',
25
+ category: 'Metafields',
26
+ quickExample: 'ecomcoder shop set-metafield --namespace=custom --key=announcement --value="Sale!" --type=single_line_text_field',
27
+ handler: async () => await import('./set-metafield.js')
28
+ });
29
+ registry.register({
30
+ command: 'shop',
31
+ subcommand: 'get-metafield',
32
+ description: 'View shop metafield values',
33
+ category: 'Metafields',
34
+ quickExample: 'ecomcoder shop get-metafield --namespace=custom --key=announcement',
35
+ handler: async () => await import('./get-metafield.js')
36
+ });
37
+ }
38
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/shop/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAClC,yBAAyB;IACzB,QAAQ,CAAC,aAAa,CAAC;QACrB,OAAO,EAAE,MAAM;QACf,WAAW,EAAE,oCAAoC;QACjD,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;QACvD,CAAC;KACF,CAAC,CAAC;IAEH,kCAAkC;IAClC,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,eAAe;QAC3B,WAAW,EAAE,qCAAqC;QAClD,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,kHAAkH;QAChI,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC;KACxD,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,eAAe;QAC3B,WAAW,EAAE,4BAA4B;QACzC,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,oEAAoE;QAClF,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC;KACxD,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * GraphQL Queries and Mutations for Shop Operations
3
+ *
4
+ * Following Single Responsibility Principle - this module only contains GraphQL strings
5
+ */
6
+ /**
7
+ * Get shop ID (needed for metafield mutations)
8
+ */
9
+ export declare const GET_SHOP_ID = "\n query getShopId {\n shop {\n id\n }\n }\n";
10
+ /**
11
+ * Get specific shop metafield by namespace and key
12
+ */
13
+ export declare const GET_SHOP_METAFIELD = "\n query getShopMetafield($namespace: String!, $key: String!) {\n shop {\n id\n metafield(namespace: $namespace, key: $key) {\n id\n namespace\n key\n value\n type\n createdAt\n updatedAt\n }\n }\n }\n";
14
+ /**
15
+ * Get shop metafields (multiple)
16
+ * Used for querying all metafields or by namespace
17
+ */
18
+ export declare const GET_SHOP_METAFIELDS = "\n query getShopMetafields($namespace: String, $first: Int) {\n shop {\n id\n metafields(namespace: $namespace, first: $first) {\n edges {\n node {\n id\n namespace\n key\n value\n type\n createdAt\n updatedAt\n }\n }\n }\n }\n }\n";
19
+ /**
20
+ * Set metafield values for shop
21
+ * Maximum 25 metafields per request, atomic operation
22
+ */
23
+ export declare const METAFIELDS_SET = "\n mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {\n metafieldsSet(metafields: $metafields) {\n metafields {\n id\n namespace\n key\n value\n type\n createdAt\n updatedAt\n }\n userErrors {\n field\n message\n code\n }\n }\n }\n";
24
+ //# sourceMappingURL=queries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../../src/commands/shop/queries.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,eAAO,MAAM,WAAW,8DAMvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,sRAe9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,mBAAmB,gXAmB/B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,cAAc,yVAmB1B,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * GraphQL Queries and Mutations for Shop Operations
3
+ *
4
+ * Following Single Responsibility Principle - this module only contains GraphQL strings
5
+ */
6
+ /**
7
+ * Get shop ID (needed for metafield mutations)
8
+ */
9
+ export const GET_SHOP_ID = `
10
+ query getShopId {
11
+ shop {
12
+ id
13
+ }
14
+ }
15
+ `;
16
+ /**
17
+ * Get specific shop metafield by namespace and key
18
+ */
19
+ export const GET_SHOP_METAFIELD = `
20
+ query getShopMetafield($namespace: String!, $key: String!) {
21
+ shop {
22
+ id
23
+ metafield(namespace: $namespace, key: $key) {
24
+ id
25
+ namespace
26
+ key
27
+ value
28
+ type
29
+ createdAt
30
+ updatedAt
31
+ }
32
+ }
33
+ }
34
+ `;
35
+ /**
36
+ * Get shop metafields (multiple)
37
+ * Used for querying all metafields or by namespace
38
+ */
39
+ export const GET_SHOP_METAFIELDS = `
40
+ query getShopMetafields($namespace: String, $first: Int) {
41
+ shop {
42
+ id
43
+ metafields(namespace: $namespace, first: $first) {
44
+ edges {
45
+ node {
46
+ id
47
+ namespace
48
+ key
49
+ value
50
+ type
51
+ createdAt
52
+ updatedAt
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ `;
59
+ /**
60
+ * Set metafield values for shop
61
+ * Maximum 25 metafields per request, atomic operation
62
+ */
63
+ export const METAFIELDS_SET = `
64
+ mutation metafieldsSet($metafields: [MetafieldsSetInput!]!) {
65
+ metafieldsSet(metafields: $metafields) {
66
+ metafields {
67
+ id
68
+ namespace
69
+ key
70
+ value
71
+ type
72
+ createdAt
73
+ updatedAt
74
+ }
75
+ userErrors {
76
+ field
77
+ message
78
+ code
79
+ }
80
+ }
81
+ }
82
+ `;
83
+ //# sourceMappingURL=queries.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queries.js","sourceRoot":"","sources":["../../../src/commands/shop/queries.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;CAM1B,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;CAejC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;;;;;;;;;;;;;;;;;;;CAmBlC,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;CAmB7B,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Shop Service - Business Logic Layer
3
+ *
4
+ * Following Service Layer Pattern - all shop business logic here
5
+ * Thin command handlers delegate to these methods
6
+ */
7
+ import type { ShopifyCredentials } from '../../lib/types.js';
8
+ import { CommandResult, SetShopMetafieldInput, GetShopMetafieldInput } from './types.js';
9
+ export declare class ShopService {
10
+ /**
11
+ * Get shop ID
12
+ * Required for metafield mutations (ownerId)
13
+ */
14
+ static getShopId(credentials: ShopifyCredentials): Promise<CommandResult<{
15
+ shopId: string;
16
+ }>>;
17
+ /**
18
+ * Set shop metafield value
19
+ */
20
+ static setMetafield(credentials: ShopifyCredentials, input: SetShopMetafieldInput): Promise<CommandResult>;
21
+ /**
22
+ * Get shop metafield(s)
23
+ * Supports:
24
+ * - Specific metafield (namespace + key)
25
+ * - All metafields in namespace (namespace only)
26
+ * - All metafields (no params)
27
+ */
28
+ static getMetafield(credentials: ShopifyCredentials, input: GetShopMetafieldInput): Promise<CommandResult>;
29
+ }
30
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/commands/shop/service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAO7D,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,qBAAqB,EAKtB,MAAM,YAAY,CAAC;AAEpB,qBAAa,WAAW;IACtB;;;OAGG;WACU,SAAS,CAAC,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,CAAC;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAsBnG;;OAEG;WACU,YAAY,CACvB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,aAAa,CAAC;IAiEzB;;;;;;OAMG;WACU,YAAY,CACvB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,aAAa,CAAC;CAmD1B"}
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Shop Service - Business Logic Layer
3
+ *
4
+ * Following Service Layer Pattern - all shop business logic here
5
+ * Thin command handlers delegate to these methods
6
+ */
7
+ import { shopifyGraphQL } from '../../lib/shopify-client.js';
8
+ import { GET_SHOP_ID, GET_SHOP_METAFIELD, GET_SHOP_METAFIELDS, METAFIELDS_SET } from './queries.js';
9
+ export class ShopService {
10
+ /**
11
+ * Get shop ID
12
+ * Required for metafield mutations (ownerId)
13
+ */
14
+ static async getShopId(credentials) {
15
+ const response = await shopifyGraphQL(credentials, GET_SHOP_ID, {});
16
+ if (!response.data?.shop) {
17
+ return {
18
+ success: false,
19
+ error: 'Shop not found'
20
+ };
21
+ }
22
+ return {
23
+ success: true,
24
+ data: {
25
+ shopId: response.data.shop.id
26
+ }
27
+ };
28
+ }
29
+ /**
30
+ * Set shop metafield value
31
+ */
32
+ static async setMetafield(credentials, input) {
33
+ // Get shop ID first
34
+ const shopIdResult = await this.getShopId(credentials);
35
+ if (!shopIdResult.success || !shopIdResult.data) {
36
+ return {
37
+ success: false,
38
+ error: shopIdResult.error || 'Failed to get shop ID'
39
+ };
40
+ }
41
+ const { shopId } = shopIdResult.data;
42
+ // Prepare metafield input
43
+ const metafieldInput = {
44
+ ownerId: shopId,
45
+ namespace: input.namespace,
46
+ key: input.key,
47
+ value: input.value,
48
+ type: input.type
49
+ };
50
+ // Execute mutation
51
+ const response = await shopifyGraphQL(credentials, METAFIELDS_SET, { metafields: [metafieldInput] });
52
+ // Check for user errors
53
+ const userErrors = response.data?.metafieldsSet?.userErrors || [];
54
+ if (userErrors.length > 0) {
55
+ const errors = userErrors
56
+ .map((e) => e.message)
57
+ .join(', ');
58
+ return {
59
+ success: false,
60
+ error: `GraphQL errors: ${errors}`
61
+ };
62
+ }
63
+ // Return the set metafield
64
+ const metafield = response.data?.metafieldsSet?.metafields?.[0];
65
+ if (!metafield) {
66
+ return {
67
+ success: false,
68
+ error: 'No metafield returned from mutation'
69
+ };
70
+ }
71
+ return {
72
+ success: true,
73
+ data: {
74
+ metafield: {
75
+ id: metafield.id,
76
+ namespace: metafield.namespace,
77
+ key: metafield.key,
78
+ value: metafield.value,
79
+ type: metafield.type,
80
+ createdAt: metafield.createdAt,
81
+ updatedAt: metafield.updatedAt
82
+ }
83
+ }
84
+ };
85
+ }
86
+ /**
87
+ * Get shop metafield(s)
88
+ * Supports:
89
+ * - Specific metafield (namespace + key)
90
+ * - All metafields in namespace (namespace only)
91
+ * - All metafields (no params)
92
+ */
93
+ static async getMetafield(credentials, input) {
94
+ // If both namespace and key provided, get specific metafield
95
+ if (input.namespace && input.key) {
96
+ const response = await shopifyGraphQL(credentials, GET_SHOP_METAFIELD, { namespace: input.namespace, key: input.key });
97
+ if (!response.data?.shop) {
98
+ return {
99
+ success: false,
100
+ error: 'Shop not found'
101
+ };
102
+ }
103
+ return {
104
+ success: true,
105
+ data: {
106
+ metafield: response.data.shop.metafield
107
+ }
108
+ };
109
+ }
110
+ // Otherwise, get multiple metafields
111
+ const response = await shopifyGraphQL(credentials, GET_SHOP_METAFIELDS, {
112
+ namespace: input.namespace || undefined,
113
+ first: 250 // Maximum allowed
114
+ });
115
+ if (!response.data?.shop) {
116
+ return {
117
+ success: false,
118
+ error: 'Shop not found'
119
+ };
120
+ }
121
+ const metafields = response.data.shop.metafields.edges.map((edge) => edge.node);
122
+ return {
123
+ success: true,
124
+ data: {
125
+ metafields,
126
+ count: metafields.length
127
+ }
128
+ };
129
+ }
130
+ }
131
+ //# sourceMappingURL=service.js.map