ecomcoder-cli 1.3.10 → 1.3.12

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 (97) hide show
  1. package/README.md +16 -0
  2. package/dist/commands/asset/delete.d.ts.map +1 -1
  3. package/dist/commands/asset/delete.js +14 -0
  4. package/dist/commands/asset/delete.js.map +1 -1
  5. package/dist/commands/asset/external-apis.d.ts +13 -0
  6. package/dist/commands/asset/external-apis.d.ts.map +1 -0
  7. package/dist/commands/asset/external-apis.js +99 -0
  8. package/dist/commands/asset/external-apis.js.map +1 -0
  9. package/dist/commands/asset/import.d.ts.map +1 -1
  10. package/dist/commands/asset/import.js +14 -0
  11. package/dist/commands/asset/import.js.map +1 -1
  12. package/dist/commands/asset/index.d.ts.map +1 -1
  13. package/dist/commands/asset/index.js +17 -0
  14. package/dist/commands/asset/index.js.map +1 -1
  15. package/dist/commands/asset/search-icons.d.ts +6 -0
  16. package/dist/commands/asset/search-icons.d.ts.map +1 -0
  17. package/dist/commands/asset/search-icons.js +84 -0
  18. package/dist/commands/asset/search-icons.js.map +1 -0
  19. package/dist/commands/asset/search-stock.d.ts +6 -0
  20. package/dist/commands/asset/search-stock.d.ts.map +1 -0
  21. package/dist/commands/asset/search-stock.js +79 -0
  22. package/dist/commands/asset/search-stock.js.map +1 -0
  23. package/dist/commands/asset/service.d.ts +13 -1
  24. package/dist/commands/asset/service.d.ts.map +1 -1
  25. package/dist/commands/asset/service.js +75 -6
  26. package/dist/commands/asset/service.js.map +1 -1
  27. package/dist/commands/asset/types.d.ts +30 -1
  28. package/dist/commands/asset/types.d.ts.map +1 -1
  29. package/dist/commands/asset/upload.d.ts.map +1 -1
  30. package/dist/commands/asset/upload.js +35 -3
  31. package/dist/commands/asset/upload.js.map +1 -1
  32. package/dist/commands/asset/utils.d.ts +13 -0
  33. package/dist/commands/asset/utils.d.ts.map +1 -0
  34. package/dist/commands/asset/utils.js +68 -0
  35. package/dist/commands/asset/utils.js.map +1 -0
  36. package/dist/commands/create-dummy-products.d.ts.map +1 -1
  37. package/dist/commands/create-dummy-products.js +14 -0
  38. package/dist/commands/create-dummy-products.js.map +1 -1
  39. package/dist/commands/create-metafield.d.ts.map +1 -1
  40. package/dist/commands/create-metafield.js +14 -0
  41. package/dist/commands/create-metafield.js.map +1 -1
  42. package/dist/commands/discount/create-basic.d.ts.map +1 -1
  43. package/dist/commands/discount/create-basic.js +14 -0
  44. package/dist/commands/discount/create-basic.js.map +1 -1
  45. package/dist/commands/discount/create-bxgy.d.ts.map +1 -1
  46. package/dist/commands/discount/create-bxgy.js +14 -0
  47. package/dist/commands/discount/create-bxgy.js.map +1 -1
  48. package/dist/commands/discount/create-shipping.d.ts.map +1 -1
  49. package/dist/commands/discount/create-shipping.js +14 -0
  50. package/dist/commands/discount/create-shipping.js.map +1 -1
  51. package/dist/commands/discount/delete.d.ts.map +1 -1
  52. package/dist/commands/discount/delete.js +14 -0
  53. package/dist/commands/discount/delete.js.map +1 -1
  54. package/dist/commands/product/add-options.d.ts.map +1 -1
  55. package/dist/commands/product/add-options.js +14 -0
  56. package/dist/commands/product/add-options.js.map +1 -1
  57. package/dist/commands/product/create-variants.d.ts.map +1 -1
  58. package/dist/commands/product/create-variants.js +14 -0
  59. package/dist/commands/product/create-variants.js.map +1 -1
  60. package/dist/commands/product/create.d.ts.map +1 -1
  61. package/dist/commands/product/create.js +14 -0
  62. package/dist/commands/product/create.js.map +1 -1
  63. package/dist/commands/product/delete-variants.d.ts.map +1 -1
  64. package/dist/commands/product/delete-variants.js +14 -0
  65. package/dist/commands/product/delete-variants.js.map +1 -1
  66. package/dist/commands/product/set-metafield.d.ts.map +1 -1
  67. package/dist/commands/product/set-metafield.js +14 -0
  68. package/dist/commands/product/set-metafield.js.map +1 -1
  69. package/dist/commands/product/update-description.d.ts.map +1 -1
  70. package/dist/commands/product/update-description.js +14 -0
  71. package/dist/commands/product/update-description.js.map +1 -1
  72. package/dist/commands/product/update-options.d.ts.map +1 -1
  73. package/dist/commands/product/update-options.js +14 -0
  74. package/dist/commands/product/update-options.js.map +1 -1
  75. package/dist/commands/product/update-price.d.ts.map +1 -1
  76. package/dist/commands/product/update-price.js +14 -0
  77. package/dist/commands/product/update-price.js.map +1 -1
  78. package/dist/commands/product/update-status.d.ts.map +1 -1
  79. package/dist/commands/product/update-status.js +14 -0
  80. package/dist/commands/product/update-status.js.map +1 -1
  81. package/dist/commands/product/update-template.d.ts.map +1 -1
  82. package/dist/commands/product/update-template.js +14 -0
  83. package/dist/commands/product/update-template.js.map +1 -1
  84. package/dist/commands/product/update-title.d.ts.map +1 -1
  85. package/dist/commands/product/update-title.js +14 -0
  86. package/dist/commands/product/update-title.js.map +1 -1
  87. package/dist/commands/set-product-rating.d.ts.map +1 -1
  88. package/dist/commands/set-product-rating.js +14 -0
  89. package/dist/commands/set-product-rating.js.map +1 -1
  90. package/dist/commands/shop/set-metafield.d.ts.map +1 -1
  91. package/dist/commands/shop/set-metafield.js +14 -0
  92. package/dist/commands/shop/set-metafield.js.map +1 -1
  93. package/dist/lib/approval.d.ts +28 -0
  94. package/dist/lib/approval.d.ts.map +1 -0
  95. package/dist/lib/approval.js +38 -0
  96. package/dist/lib/approval.js.map +1 -0
  97. package/package.json +1 -1
package/README.md CHANGED
@@ -128,6 +128,22 @@ You can also manually provide the session ID:
128
128
  ecomcoder products list --session-id=your-session-id
129
129
  ```
130
130
 
131
+ ## Safety Features
132
+
133
+ ### User Approval for Destructive Operations
134
+
135
+ All commands that modify your live Shopify store (create, update, delete operations) require user confirmation before execution. This prevents accidental changes to your production store.
136
+
137
+ **Commands requiring approval:**
138
+ - Product updates (price, title, description, status, etc.)
139
+ - Product/variant creation and deletion
140
+ - Discount creation and deletion
141
+ - Metafield modifications
142
+
143
+ **Read-only commands** (like `products list`, `product get`) execute immediately without approval prompts.
144
+
145
+ When used with the EcomCoder app, you'll see a confirmation dialog before any destructive operation is executed. The CLI will wait for your approval before proceeding.
146
+
131
147
  ## Development
132
148
 
133
149
  ### Setup
@@ -1 +1 @@
1
- {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/delete.ts"],"names":[],"mappings":"AAAA;;GAEG;AAuBH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAmC/D"}
1
+ {"version":3,"file":"delete.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/delete.ts"],"names":[],"mappings":"AAAA;;GAEG;AAwBH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAkD/D"}
@@ -4,6 +4,7 @@
4
4
  import { getCredentials, getSessionId } from '../../lib/api-client.js';
5
5
  import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
6
6
  import { AssetService } from './service.js';
7
+ import { requestApproval } from '../../lib/approval.js';
7
8
  function showHelp() {
8
9
  console.log(`
9
10
  Delete Asset
@@ -35,6 +36,19 @@ export async function run(argv = process.argv.slice(2)) {
35
36
  try {
36
37
  const sessionId = getSessionId(args.sessionId);
37
38
  const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
39
+ // Request approval before executing
40
+ const approved = await requestApproval({
41
+ command: `ecomcoder asset delete --id=${args.id}`,
42
+ message: `This will permanently delete the asset from your live Shopify store. This action cannot be undone.`,
43
+ riskLevel: 'high'
44
+ });
45
+ if (!approved) {
46
+ console.log(JSON.stringify({
47
+ success: false,
48
+ error: 'Operation cancelled by user'
49
+ }));
50
+ process.exit(1);
51
+ }
38
52
  const result = await AssetService.delete(credentials, {
39
53
  id: args.id
40
54
  });
@@ -1 +1 @@
1
- {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/commands/asset/delete.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYb,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,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;QACH,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,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE;YACpD,EAAE,EAAE,IAAI,CAAC,EAAE;SACZ,CAAC,CAAC;QAEH,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"}
1
+ {"version":3,"file":"delete.js","sourceRoot":"","sources":["../../../src/commands/asset/delete.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;CAYb,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,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;QACH,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,QAAQ,GAAG,MAAM,eAAe,CAAC;YACrC,OAAO,EAAE,+BAA+B,IAAI,CAAC,EAAE,EAAE;YACjD,OAAO,EAAE,oGAAoG;YAC7G,SAAS,EAAE,MAAM;SAClB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACzB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,6BAA6B;aACrC,CAAC,CAAC,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE;YACpD,EAAE,EAAE,IAAI,CAAC,EAAE;SACZ,CAAC,CAAC;QAEH,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,13 @@
1
+ /**
2
+ * External API Integrations
3
+ * Handles stock images (Pexels) and icons (Lucide)
4
+ */
5
+ import { StockImage, SearchStockInput, Icon, SearchIconsInput } from './types.js';
6
+ /**
7
+ * Pexels API Client
8
+ * Free stock photos API
9
+ * Rate limit: 200/hour, 20,000/month (free tier)
10
+ */
11
+ export declare function searchPexelsImages(input: SearchStockInput): Promise<StockImage[]>;
12
+ export declare function searchLucideIcons(input: SearchIconsInput): Promise<Icon[]>;
13
+ //# sourceMappingURL=external-apis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-apis.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/external-apis.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,IAAI,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAElF;;;;GAIG;AACH,wBAAsB,kBAAkB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAkDvF;AAkCD,wBAAsB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAkBhF"}
@@ -0,0 +1,99 @@
1
+ /**
2
+ * External API Integrations
3
+ * Handles stock images (Pexels) and icons (Lucide)
4
+ */
5
+ /**
6
+ * Pexels API Client
7
+ * Free stock photos API
8
+ * Rate limit: 200/hour, 20,000/month (free tier)
9
+ */
10
+ export async function searchPexelsImages(input) {
11
+ const apiKey = process.env.PEXELS_API_KEY;
12
+ if (!apiKey) {
13
+ throw new Error('PEXELS_API_KEY environment variable not set. Get your free API key at https://www.pexels.com/api/');
14
+ }
15
+ const limit = Math.min(input.limit || 10, 80); // Max 80 per request
16
+ const params = new URLSearchParams({
17
+ query: input.query,
18
+ per_page: limit.toString(),
19
+ });
20
+ if (input.orientation) {
21
+ params.append('orientation', input.orientation);
22
+ }
23
+ if (input.size) {
24
+ params.append('size', input.size);
25
+ }
26
+ if (input.color) {
27
+ params.append('color', input.color);
28
+ }
29
+ const response = await fetch(`https://api.pexels.com/v1/search?${params}`, {
30
+ headers: {
31
+ 'Authorization': apiKey
32
+ }
33
+ });
34
+ if (!response.ok) {
35
+ if (response.status === 429) {
36
+ throw new Error('Pexels rate limit exceeded. Free tier: 200/hour, 20,000/month.');
37
+ }
38
+ throw new Error(`Pexels API error: ${response.status} ${response.statusText}`);
39
+ }
40
+ const data = await response.json();
41
+ return data.photos.map((photo) => ({
42
+ id: photo.id,
43
+ url: photo.src.large2x || photo.src.large, // High quality image
44
+ photographer: photo.photographer,
45
+ photographerUrl: photo.photographer_url,
46
+ width: photo.width,
47
+ height: photo.height,
48
+ alt: photo.alt || input.query,
49
+ avgColor: photo.avg_color
50
+ }));
51
+ }
52
+ /**
53
+ * Lucide Icons Search
54
+ * Open-source icon library with 1,667+ icons
55
+ * No API key required - uses CDN
56
+ */
57
+ // Embedded icon metadata for fast search
58
+ // This is a curated subset - full list at https://lucide.dev/icons/
59
+ const LUCIDE_ICONS = [
60
+ { name: 'shopping-cart', tags: ['cart', 'shop', 'buy', 'purchase', 'ecommerce'], category: 'ecommerce' },
61
+ { name: 'shopping-bag', tags: ['bag', 'shop', 'buy', 'purchase', 'ecommerce'], category: 'ecommerce' },
62
+ { name: 'credit-card', tags: ['payment', 'card', 'pay', 'money'], category: 'payment' },
63
+ { name: 'heart', tags: ['like', 'favorite', 'love', 'wishlist'], category: 'social' },
64
+ { name: 'star', tags: ['favorite', 'rating', 'review'], category: 'social' },
65
+ { name: 'user', tags: ['account', 'profile', 'person'], category: 'user' },
66
+ { name: 'search', tags: ['find', 'magnifier', 'look'], category: 'ui' },
67
+ { name: 'menu', tags: ['hamburger', 'navigation', 'nav'], category: 'ui' },
68
+ { name: 'x', tags: ['close', 'cancel', 'dismiss'], category: 'ui' },
69
+ { name: 'check', tags: ['success', 'done', 'complete'], category: 'ui' },
70
+ { name: 'arrow-right', tags: ['next', 'forward', 'direction'], category: 'arrows' },
71
+ { name: 'arrow-left', tags: ['back', 'previous', 'direction'], category: 'arrows' },
72
+ { name: 'home', tags: ['house', 'main', 'start'], category: 'ui' },
73
+ { name: 'mail', tags: ['email', 'message', 'envelope'], category: 'communication' },
74
+ { name: 'phone', tags: ['call', 'contact', 'telephone'], category: 'communication' },
75
+ { name: 'truck', tags: ['delivery', 'shipping', 'transport'], category: 'ecommerce' },
76
+ { name: 'package', tags: ['box', 'product', 'shipping'], category: 'ecommerce' },
77
+ { name: 'gift', tags: ['present', 'box', 'surprise'], category: 'ecommerce' },
78
+ { name: 'tag', tags: ['price', 'label', 'discount'], category: 'ecommerce' },
79
+ { name: 'percent', tags: ['discount', 'sale', 'offer'], category: 'ecommerce' },
80
+ // Add more as needed - this is just a starter set
81
+ ];
82
+ export async function searchLucideIcons(input) {
83
+ const query = input.query.toLowerCase();
84
+ const limit = input.limit || 10;
85
+ // Search in name and tags
86
+ const results = LUCIDE_ICONS.filter(icon => {
87
+ return icon.name.includes(query) ||
88
+ icon.tags.some(tag => tag.includes(query)) ||
89
+ icon.category?.includes(query);
90
+ });
91
+ // Return top matches with CDN URLs
92
+ return results.slice(0, limit).map(icon => ({
93
+ name: icon.name,
94
+ url: `https://cdn.jsdelivr.net/npm/lucide-static@latest/icons/${icon.name}.svg`,
95
+ tags: icon.tags,
96
+ category: icon.category
97
+ }));
98
+ }
99
+ //# sourceMappingURL=external-apis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"external-apis.js","sourceRoot":"","sources":["../../../src/commands/asset/external-apis.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/import.ts"],"names":[],"mappings":"AAAA;;GAEG;AAyBH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAoC/D"}
1
+ {"version":3,"file":"import.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/import.ts"],"names":[],"mappings":"AAAA;;GAEG;AA0BH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAmD/D"}
@@ -4,6 +4,7 @@
4
4
  import { getCredentials, getSessionId } from '../../lib/api-client.js';
5
5
  import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
6
6
  import { AssetService } from './service.js';
7
+ import { requestApproval } from '../../lib/approval.js';
7
8
  function showHelp() {
8
9
  console.log(`
9
10
  Bulk Import Assets
@@ -37,6 +38,19 @@ export async function run(argv = process.argv.slice(2)) {
37
38
  try {
38
39
  const sessionId = getSessionId(args.sessionId);
39
40
  const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
41
+ // Request approval before executing
42
+ const approved = await requestApproval({
43
+ command: `ecomcoder asset import --directory=${args.directory}`,
44
+ message: `This will bulk import assets to your live Shopify store`,
45
+ riskLevel: 'moderate'
46
+ });
47
+ if (!approved) {
48
+ console.log(JSON.stringify({
49
+ success: false,
50
+ error: 'Operation cancelled by user'
51
+ }));
52
+ process.exit(1);
53
+ }
40
54
  const result = await AssetService.import(credentials, {
41
55
  directory: args.directory,
42
56
  pattern: args.pattern
@@ -1 +1 @@
1
- {"version":3,"file":"import.js","sourceRoot":"","sources":["../../../src/commands/asset/import.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;CAcb,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,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,wCAAwC;SAChD,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,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,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE;YACpD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,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"}
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../../src/commands/asset/import.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAExD,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;CAcb,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,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3B,OAAO,EAAE,KAAK;YACd,KAAK,EAAE,wCAAwC;SAChD,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,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,QAAQ,GAAG,MAAM,eAAe,CAAC;YACrC,OAAO,EAAE,sCAAsC,IAAI,CAAC,SAAS,EAAE;YAC/D,OAAO,EAAE,yDAAyD;YAClE,SAAS,EAAE,UAAU;SACtB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;gBACzB,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,6BAA6B;aACrC,CAAC,CAAC,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE;YACpD,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,OAAO,EAAE,IAAI,CAAC,OAAO;SACtB,CAAC,CAAC;QAEH,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"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAgB,qBAAqB,IAAI,IAAI,CAwD5C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAgB,qBAAqB,IAAI,IAAI,CA2E5C"}
@@ -54,5 +54,22 @@ export function registerAssetCommands() {
54
54
  quickExample: 'ecomcoder asset import --directory=./images --pattern="*.png"',
55
55
  handler: async () => await import('./import.js')
56
56
  });
57
+ // External resources
58
+ registry.register({
59
+ command: 'asset',
60
+ subcommand: 'search-stock',
61
+ description: 'Search free stock photos (Pexels)',
62
+ category: 'Search',
63
+ quickExample: 'ecomcoder asset search-stock --query="mountains" --limit=5',
64
+ handler: async () => await import('./search-stock.js')
65
+ });
66
+ registry.register({
67
+ command: 'asset',
68
+ subcommand: 'search-icons',
69
+ description: 'Search open-source icons (Lucide)',
70
+ category: 'Search',
71
+ quickExample: 'ecomcoder asset search-icons --query="cart"',
72
+ handler: async () => await import('./search-icons.js')
73
+ });
57
74
  }
58
75
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/asset/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,UAAU,qBAAqB;IACnC,iBAAiB;IACjB,QAAQ,CAAC,aAAa,CAAC;QACrB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,6CAA6C;QAC1D,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC;KACF,CAAC,CAAC;IAEH,kBAAkB;IAClB,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,yBAAyB;QACtC,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,qDAAqD;QACnE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,yBAAyB;QACtC,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,uDAAuD;QACrE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC;KAC9C,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,2BAA2B;QACxC,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,0DAA0D;QACxE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,oBAAoB;IACpB,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,iBAAiB;QAC9B,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,8CAA8C;QAC5D,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC;KAC/C,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,mCAAmC;QAChD,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,+DAA+D;QAC7E,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;KACjD,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/asset/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AACzD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAE5D,MAAM,UAAU,qBAAqB;IACnC,iBAAiB;IACjB,QAAQ,CAAC,aAAa,CAAC;QACrB,OAAO,EAAE,OAAO;QAChB,WAAW,EAAE,6CAA6C;QAC1D,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC;KACF,CAAC,CAAC;IAEH,kBAAkB;IAClB,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,yBAAyB;QACtC,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,qDAAqD;QACnE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,KAAK;QACjB,WAAW,EAAE,yBAAyB;QACtC,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,uDAAuD;QACrE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,UAAU,CAAC;KAC9C,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,2BAA2B;QACxC,QAAQ,EAAE,MAAM;QAChB,YAAY,EAAE,0DAA0D;QACxE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,oBAAoB;IACpB,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,MAAM;QAClB,WAAW,EAAE,iBAAiB;QAC9B,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,8CAA8C;QAC5D,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,WAAW,CAAC;KAC/C,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,QAAQ;QACpB,WAAW,EAAE,mCAAmC;QAChD,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,+DAA+D;QAC7E,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,aAAa,CAAC;KACjD,CAAC,CAAC;IAEH,qBAAqB;IACrB,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,cAAc;QAC1B,WAAW,EAAE,mCAAmC;QAChD,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,4DAA4D;QAC1E,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,mBAAmB,CAAC;KACvD,CAAC,CAAC;IAEH,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,cAAc;QAC1B,WAAW,EAAE,mCAAmC;QAChD,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,6CAA6C;QAC3D,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,mBAAmB,CAAC;KACvD,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Search Icons Command
3
+ * Search open-source icons from Lucide library
4
+ */
5
+ export declare function run(argv?: string[]): Promise<void>;
6
+ //# sourceMappingURL=search-icons.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-icons.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/search-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqDH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAiC/D"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Search Icons Command
3
+ * Search open-source icons from Lucide library
4
+ */
5
+ import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
6
+ import { AssetService } from './service.js';
7
+ function showHelp() {
8
+ console.log(`
9
+ Search Icons (Lucide)
10
+
11
+ USAGE:
12
+ ecomcoder asset search-icons --query=<search> [OPTIONS]
13
+
14
+ OPTIONS:
15
+ --query <text> Search query (required)
16
+ --limit <number> Max results (default: 10)
17
+ --help, -h Show this help message
18
+
19
+ ABOUT LUCIDE:
20
+ - Open-source icon library (ISC license)
21
+ - 1,667+ icons and growing
22
+ - SVG format (lightweight, customizable)
23
+ - No API key required
24
+ - Free for commercial use
25
+
26
+ EXAMPLES:
27
+ # Search for shopping cart icons
28
+ ecomcoder asset search-icons --query="cart"
29
+
30
+ # Search for payment icons
31
+ ecomcoder asset search-icons --query="credit card"
32
+
33
+ # Search for social icons
34
+ ecomcoder asset search-icons --query="heart" --limit=5
35
+
36
+ USAGE IN LIQUID:
37
+ Icons are returned as CDN URLs. Use directly in your theme:
38
+
39
+ <img src="{{icon_url}}" alt="Icon" width="24" height="24">
40
+
41
+ Or download and customize:
42
+
43
+ ecomcoder asset upload --url=<icon_url>
44
+
45
+ CATEGORIES:
46
+ ecommerce: cart, bag, tag, truck, package, gift
47
+ payment: credit-card, dollar, percent
48
+ social: heart, star, share, thumbs-up
49
+ ui: menu, search, x, check, arrow
50
+ communication: mail, phone, message
51
+ `);
52
+ process.exit(0);
53
+ }
54
+ export async function run(argv = process.argv.slice(2)) {
55
+ if (hasHelpFlag(argv)) {
56
+ showHelp();
57
+ }
58
+ const args = parseArgs(argv);
59
+ if (!args.query) {
60
+ console.error(JSON.stringify({
61
+ success: false,
62
+ error: 'Missing required argument: --query'
63
+ }));
64
+ process.exit(1);
65
+ }
66
+ try {
67
+ const result = await AssetService.searchIcons({
68
+ query: args.query,
69
+ limit: args.limit ? parseInt(args.limit) : undefined
70
+ });
71
+ console.log(JSON.stringify(result, null, 2));
72
+ if (!result.success) {
73
+ process.exit(1);
74
+ }
75
+ }
76
+ catch (error) {
77
+ console.error(JSON.stringify({
78
+ success: false,
79
+ error: error.message || 'Unknown error occurred'
80
+ }));
81
+ process.exit(1);
82
+ }
83
+ }
84
+ //# sourceMappingURL=search-icons.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-icons.js","sourceRoot":"","sources":["../../../src/commands/asset/search-icons.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2Cb,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,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,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC;YAC5C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;SACrD,CAAC,CAAC;QAEH,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,6 @@
1
+ /**
2
+ * Search Stock Images Command
3
+ * Search free stock photos from Pexels API
4
+ */
5
+ export declare function run(argv?: string[]): Promise<void>;
6
+ //# sourceMappingURL=search-stock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-stock.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/search-stock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6CH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAoC/D"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Search Stock Images Command
3
+ * Search free stock photos from Pexels API
4
+ */
5
+ import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
6
+ import { AssetService } from './service.js';
7
+ function showHelp() {
8
+ console.log(`
9
+ Search Stock Images (Pexels)
10
+
11
+ USAGE:
12
+ ecomcoder asset search-stock --query=<search> [OPTIONS]
13
+
14
+ OPTIONS:
15
+ --query <text> Search query (required)
16
+ --limit <number> Max results (default: 10, max: 80)
17
+ --orientation <type> Filter by orientation (landscape|portrait|square)
18
+ --size <size> Filter by size (large|medium|small)
19
+ --color <color> Filter by color (e.g., red, blue, green)
20
+ --help, -h Show this help message
21
+
22
+ SETUP:
23
+ Get your free API key at: https://www.pexels.com/api/
24
+ Set environment variable: export PEXELS_API_KEY=your-key-here
25
+
26
+ EXAMPLES:
27
+ # Search for mountains
28
+ ecomcoder asset search-stock --query="mountains"
29
+
30
+ # Landscape photos of ocean
31
+ ecomcoder asset search-stock --query="ocean" --orientation=landscape --limit=5
32
+
33
+ # Large photos of sunset
34
+ ecomcoder asset search-stock --query="sunset" --size=large
35
+
36
+ WORKFLOW:
37
+ 1. Search for stock images
38
+ 2. Use returned URL with: ecomcoder asset upload --url=<url>
39
+ 3. Asset is uploaded to your Shopify store
40
+
41
+ RATE LIMITS:
42
+ Free tier: 200 requests/hour, 20,000 requests/month
43
+ `);
44
+ process.exit(0);
45
+ }
46
+ export async function run(argv = process.argv.slice(2)) {
47
+ if (hasHelpFlag(argv)) {
48
+ showHelp();
49
+ }
50
+ const args = parseArgs(argv);
51
+ if (!args.query) {
52
+ console.error(JSON.stringify({
53
+ success: false,
54
+ error: 'Missing required argument: --query'
55
+ }));
56
+ process.exit(1);
57
+ }
58
+ try {
59
+ const result = await AssetService.searchStock({
60
+ query: args.query,
61
+ limit: args.limit ? parseInt(args.limit) : undefined,
62
+ orientation: args.orientation,
63
+ size: args.size,
64
+ color: args.color
65
+ });
66
+ console.log(JSON.stringify(result, null, 2));
67
+ if (!result.success) {
68
+ process.exit(1);
69
+ }
70
+ }
71
+ catch (error) {
72
+ console.error(JSON.stringify({
73
+ success: false,
74
+ error: error.message || 'Unknown error occurred'
75
+ }));
76
+ process.exit(1);
77
+ }
78
+ }
79
+ //# sourceMappingURL=search-stock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-stock.js","sourceRoot":"","sources":["../../../src/commands/asset/search-stock.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAE5C,SAAS,QAAQ;IACf,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmCb,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,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,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC;YAC5C,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;YACpD,WAAW,EAAE,IAAI,CAAC,WAA8D;YAChF,IAAI,EAAE,IAAI,CAAC,IAAgD;YAC3D,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QAEH,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"}
@@ -5,7 +5,7 @@
5
5
  * Following Service Layer Pattern
6
6
  */
7
7
  import { ShopifyCredentials } from '../../lib/types.js';
8
- import { CommandResult, UploadAssetInput, ListAssetsInput, GetAssetInput, DeleteAssetInput, ImportAssetsInput, FormattedAsset } from './types.js';
8
+ import { CommandResult, UploadAssetInput, ListAssetsInput, GetAssetInput, DeleteAssetInput, ImportAssetsInput, FormattedAsset, SearchStockInput, StockImage, SearchIconsInput, Icon } from './types.js';
9
9
  export declare class AssetService {
10
10
  /**
11
11
  * Upload single asset to Shopify
@@ -46,5 +46,17 @@ export declare class AssetService {
46
46
  failed: number;
47
47
  errors: string[];
48
48
  }>>;
49
+ /**
50
+ * Search stock images from Pexels
51
+ */
52
+ static searchStock(input: SearchStockInput): Promise<CommandResult<{
53
+ images: StockImage[];
54
+ }>>;
55
+ /**
56
+ * Search icons from Lucide
57
+ */
58
+ static searchIcons(input: SearchIconsInput): Promise<CommandResult<{
59
+ icons: Icon[];
60
+ }>>;
49
61
  }
50
62
  //# sourceMappingURL=service.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAYxD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAMf,MAAM,YAAY,CAAC;AAEpB,qBAAa,YAAY;IACvB;;;;;;;OAOG;WACU,MAAM,CACjB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IAiJpD;;OAEG;WACU,IAAI,CACf,WAAW,EAAE,kBAAkB,EAC/B,KAAK,GAAE,eAAoB,GAC1B,OAAO,CAAC,aAAa,CAAC;QAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAyChG;;OAEG;WACU,GAAG,CACd,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IA6BpD;;OAEG;WACU,MAAM,CACjB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA+BhD;;OAEG;WACU,MAAM,CACjB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAkDlF"}
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/commands/asset/service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAaxD,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EAMd,gBAAgB,EAChB,UAAU,EACV,gBAAgB,EAChB,IAAI,EACL,MAAM,YAAY,CAAC;AAEpB,qBAAa,YAAY;IACvB;;;;;;;OAOG;WACU,MAAM,CACjB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IAiLpD;;OAEG;WACU,IAAI,CACf,WAAW,EAAE,kBAAkB,EAC/B,KAAK,GAAE,eAAoB,GAC1B,OAAO,CAAC,aAAa,CAAC;QAAE,MAAM,EAAE,cAAc,EAAE,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;IAyChG;;OAEG;WACU,GAAG,CACd,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,aAAa,GACnB,OAAO,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;IA6BpD;;OAEG;WACU,MAAM,CACjB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC;QAAE,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IA+BhD;;OAEG;WACU,MAAM,CACjB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,aAAa,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAmDjF;;OAEG;WACU,WAAW,CACtB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC;QAAE,MAAM,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAC;IAiBnD;;OAEG;WACU,WAAW,CACtB,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,IAAI,EAAE,CAAA;KAAE,CAAC,CAAC;CAgB7C"}
@@ -9,6 +9,7 @@ import * as fs from 'fs';
9
9
  import * as path from 'path';
10
10
  import FormData from 'form-data';
11
11
  import { URL } from 'url';
12
+ import { downloadUrlToTemp } from './utils.js';
12
13
  import { FILE_CREATE, FILES_LIST, FILE_GET, FILE_DELETE, STAGED_UPLOADS_CREATE } from './queries.js';
13
14
  export class AssetService {
14
15
  /**
@@ -20,18 +21,42 @@ export class AssetService {
20
21
  * 3. Create file record in Shopify
21
22
  */
22
23
  static async upload(credentials, input) {
24
+ let filePath;
25
+ let cleanup = null;
23
26
  try {
27
+ // Validate: must provide either --file or --url
28
+ if (!input.file && !input.url) {
29
+ return {
30
+ success: false,
31
+ error: 'Must provide either --file or --url'
32
+ };
33
+ }
34
+ if (input.file && input.url) {
35
+ return {
36
+ success: false,
37
+ error: 'Cannot use both --file and --url'
38
+ };
39
+ }
40
+ // If URL provided, download to temp file
41
+ if (input.url) {
42
+ const downloaded = await downloadUrlToTemp(input.url);
43
+ filePath = downloaded.path;
44
+ cleanup = downloaded.cleanup;
45
+ }
46
+ else {
47
+ filePath = input.file;
48
+ }
24
49
  // Step 1: Validate file exists
25
- if (!fs.existsSync(input.file)) {
50
+ if (!fs.existsSync(filePath)) {
26
51
  return {
27
52
  success: false,
28
- error: `File not found: ${input.file}`
53
+ error: `File not found: ${filePath}`
29
54
  };
30
55
  }
31
56
  // Step 2: Get file metadata
32
- const stats = fs.statSync(input.file);
33
- const fileName = path.basename(input.file);
34
- const mimeType = getMimeType(input.file);
57
+ const stats = fs.statSync(filePath);
58
+ const fileName = path.basename(filePath);
59
+ const mimeType = getMimeType(filePath);
35
60
  const fileSize = stats.size;
36
61
  // Step 3: Detect content type
37
62
  const contentType = input.contentType || detectContentType(mimeType);
@@ -56,7 +81,7 @@ export class AssetService {
56
81
  // Step 5: Upload file to signed URL
57
82
  // CRITICAL: GCS signed URLs require multipart/form-data with parameters
58
83
  // Reference: https://community.shopify.com/c/shopify-apis-and-sdks/error-uploading-file-after-stageduploadscreate/td-p/1718315
59
- const fileBuffer = fs.readFileSync(input.file);
84
+ const fileBuffer = fs.readFileSync(filePath);
60
85
  const form = new FormData();
61
86
  // Add parameters from stagedUploadsCreate response FIRST (required for GCS auth)
62
87
  target.parameters.forEach(param => {
@@ -143,6 +168,12 @@ export class AssetService {
143
168
  error: error.message || 'Unknown error during upload'
144
169
  };
145
170
  }
171
+ finally {
172
+ // Cleanup temp file if we downloaded from URL
173
+ if (cleanup) {
174
+ cleanup();
175
+ }
176
+ }
146
177
  }
147
178
  /**
148
179
  * List all assets
@@ -282,6 +313,44 @@ export class AssetService {
282
313
  };
283
314
  }
284
315
  }
316
+ /**
317
+ * Search stock images from Pexels
318
+ */
319
+ static async searchStock(input) {
320
+ try {
321
+ const { searchPexelsImages } = await import('./external-apis.js');
322
+ const images = await searchPexelsImages(input);
323
+ return {
324
+ success: true,
325
+ data: { images }
326
+ };
327
+ }
328
+ catch (error) {
329
+ return {
330
+ success: false,
331
+ error: error.message || 'Unknown error during stock image search'
332
+ };
333
+ }
334
+ }
335
+ /**
336
+ * Search icons from Lucide
337
+ */
338
+ static async searchIcons(input) {
339
+ try {
340
+ const { searchLucideIcons } = await import('./external-apis.js');
341
+ const icons = await searchLucideIcons(input);
342
+ return {
343
+ success: true,
344
+ data: { icons }
345
+ };
346
+ }
347
+ catch (error) {
348
+ return {
349
+ success: false,
350
+ error: error.message || 'Unknown error during icon search'
351
+ };
352
+ }
353
+ }
285
354
  }
286
355
  // Helper functions
287
356
  function getMimeType(filePath) {