ecomcoder-cli 1.3.13 → 1.3.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/collection/get-product-collections.d.ts +7 -0
- package/dist/commands/collection/get-product-collections.d.ts.map +1 -0
- package/dist/commands/collection/get-product-collections.js +99 -0
- package/dist/commands/collection/get-product-collections.js.map +1 -0
- package/dist/commands/collection/get.d.ts +7 -0
- package/dist/commands/collection/get.d.ts.map +1 -0
- package/dist/commands/collection/get.js +80 -0
- package/dist/commands/collection/get.js.map +1 -0
- package/dist/commands/collection/index.d.ts +10 -0
- package/dist/commands/collection/index.d.ts.map +1 -0
- package/dist/commands/collection/index.js +54 -0
- package/dist/commands/collection/index.js.map +1 -0
- package/dist/commands/collection/list-products.d.ts +7 -0
- package/dist/commands/collection/list-products.d.ts.map +1 -0
- package/dist/commands/collection/list-products.js +105 -0
- package/dist/commands/collection/list-products.js.map +1 -0
- package/dist/commands/collection/list.d.ts +7 -0
- package/dist/commands/collection/list.d.ts.map +1 -0
- package/dist/commands/collection/list.js +105 -0
- package/dist/commands/collection/list.js.map +1 -0
- package/dist/commands/collection/queries.d.ts +32 -0
- package/dist/commands/collection/queries.d.ts.map +1 -0
- package/dist/commands/collection/queries.js +158 -0
- package/dist/commands/collection/queries.js.map +1 -0
- package/dist/commands/collection/service.d.ts +53 -0
- package/dist/commands/collection/service.d.ts.map +1 -0
- package/dist/commands/collection/service.js +232 -0
- package/dist/commands/collection/service.js.map +1 -0
- package/dist/commands/collection/types.d.ts +156 -0
- package/dist/commands/collection/types.d.ts.map +1 -0
- package/dist/commands/collection/types.js +6 -0
- package/dist/commands/collection/types.js.map +1 -0
- package/dist/commands/collection/utils.d.ts +33 -0
- package/dist/commands/collection/utils.d.ts.map +1 -0
- package/dist/commands/collection/utils.js +84 -0
- package/dist/commands/collection/utils.js.map +1 -0
- package/dist/commands/image/generate.d.ts +6 -0
- package/dist/commands/image/generate.d.ts.map +1 -0
- package/dist/commands/image/generate.js +135 -0
- package/dist/commands/image/generate.js.map +1 -0
- package/dist/commands/image/index.d.ts +5 -0
- package/dist/commands/image/index.d.ts.map +1 -0
- package/dist/commands/image/index.js +25 -0
- package/dist/commands/image/index.js.map +1 -0
- package/dist/commands/image/openai.d.ts +19 -0
- package/dist/commands/image/openai.d.ts.map +1 -0
- package/dist/commands/image/openai.js +35 -0
- package/dist/commands/image/openai.js.map +1 -0
- package/dist/commands/image/service.d.ts +31 -0
- package/dist/commands/image/service.d.ts.map +1 -0
- package/dist/commands/image/service.js +72 -0
- package/dist/commands/image/service.js.map +1 -0
- package/dist/lib/approval.d.ts +19 -4
- package/dist/lib/approval.d.ts.map +1 -1
- package/dist/lib/approval.js +26 -5
- package/dist/lib/approval.js.map +1 -1
- package/dist/lib/config.d.ts +52 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +83 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/types.d.ts +5 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/package.json +4 -2
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection Utility Functions
|
|
3
|
+
* Pure functions for data transformation and validation
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Normalize collection ID to both GID and numeric formats
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeCollectionId(id) {
|
|
9
|
+
if (id.startsWith('gid://shopify/Collection/')) {
|
|
10
|
+
return {
|
|
11
|
+
gid: id,
|
|
12
|
+
numeric: id.split('/').pop() || ''
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
gid: `gid://shopify/Collection/${id}`,
|
|
17
|
+
numeric: id
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Normalize product ID to both GID and numeric formats
|
|
22
|
+
*/
|
|
23
|
+
export function normalizeProductId(id) {
|
|
24
|
+
if (id.startsWith('gid://shopify/Product/')) {
|
|
25
|
+
return {
|
|
26
|
+
gid: id,
|
|
27
|
+
numeric: id.split('/').pop() || ''
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
gid: `gid://shopify/Product/${id}`,
|
|
32
|
+
numeric: id
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Format collection for CLI output
|
|
37
|
+
*/
|
|
38
|
+
export function formatCollection(collection) {
|
|
39
|
+
return {
|
|
40
|
+
id: collection.id,
|
|
41
|
+
title: collection.title,
|
|
42
|
+
handle: collection.handle,
|
|
43
|
+
description: collection.description,
|
|
44
|
+
productsCount: collection.productsCount,
|
|
45
|
+
sortOrder: collection.sortOrder,
|
|
46
|
+
updatedAt: collection.updatedAt,
|
|
47
|
+
image: collection.image ? {
|
|
48
|
+
url: collection.image.url,
|
|
49
|
+
altText: collection.image.altText
|
|
50
|
+
} : undefined
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Check if GraphQL response has errors
|
|
55
|
+
*/
|
|
56
|
+
export function hasGraphQLErrors(response) {
|
|
57
|
+
return !!(response.errors && response.errors.length > 0);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Extract GraphQL error messages
|
|
61
|
+
*/
|
|
62
|
+
export function extractGraphQLErrors(response) {
|
|
63
|
+
if (!response.errors || response.errors.length === 0) {
|
|
64
|
+
return 'Unknown GraphQL error';
|
|
65
|
+
}
|
|
66
|
+
return response.errors
|
|
67
|
+
.map((err) => err.message)
|
|
68
|
+
.join(', ');
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Format Shopify user errors
|
|
72
|
+
*/
|
|
73
|
+
export function formatUserErrors(errors) {
|
|
74
|
+
if (!errors || errors.length === 0) {
|
|
75
|
+
return 'Unknown error';
|
|
76
|
+
}
|
|
77
|
+
return errors
|
|
78
|
+
.map(err => {
|
|
79
|
+
const field = err.field ? err.field.join('.') : 'general';
|
|
80
|
+
return `${field}: ${err.message}`;
|
|
81
|
+
})
|
|
82
|
+
.join(', ');
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/collection/utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,EAAU;IAC9C,IAAI,EAAE,CAAC,UAAU,CAAC,2BAA2B,CAAC,EAAE,CAAC;QAC/C,OAAO;YACL,GAAG,EAAE,EAAE;YACP,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE;SACnC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG,EAAE,4BAA4B,EAAE,EAAE;QACrC,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,EAAU;IAC3C,IAAI,EAAE,CAAC,UAAU,CAAC,wBAAwB,CAAC,EAAE,CAAC;QAC5C,OAAO;YACL,GAAG,EAAE,EAAE;YACP,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE;SACnC,CAAC;IACJ,CAAC;IAED,OAAO;QACL,GAAG,EAAE,yBAAyB,EAAE,EAAE;QAClC,OAAO,EAAE,EAAE;KACZ,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,UAAe;IAC9C,OAAO;QACL,EAAE,EAAE,UAAU,CAAC,EAAE;QACjB,KAAK,EAAE,UAAU,CAAC,KAAK;QACvB,MAAM,EAAE,UAAU,CAAC,MAAM;QACzB,WAAW,EAAE,UAAU,CAAC,WAAW;QACnC,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,SAAS,EAAE,UAAU,CAAC,SAAS;QAC/B,SAAS,EAAE,UAAU,CAAC,SAAS;QAC/B,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC;YACxB,GAAG,EAAE,UAAU,CAAC,KAAK,CAAC,GAAG;YACzB,OAAO,EAAE,UAAU,CAAC,KAAK,CAAC,OAAO;SAClC,CAAC,CAAC,CAAC,SAAS;KACd,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAa;IAC5C,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAa;IAChD,IAAI,CAAC,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrD,OAAO,uBAAuB,CAAC;IACjC,CAAC;IAED,OAAO,QAAQ,CAAC,MAAM;SACnB,GAAG,CAAC,CAAC,GAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;SAC9B,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,MAAoD;IACnF,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,OAAO,MAAM;SACV,GAAG,CAAC,GAAG,CAAC,EAAE;QACT,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC1D,OAAO,GAAG,KAAK,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;IACpC,CAAC,CAAC;SACD,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../../src/commands/image/generate.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAqEH,wBAAsB,GAAG,CAAC,IAAI,GAAE,MAAM,EAA0B,iBAwE/D"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generate AI Image Command
|
|
3
|
+
* Generate custom images using DALL-E 3
|
|
4
|
+
*/
|
|
5
|
+
import { getCredentials, getSessionId } from '../../lib/api-client.js';
|
|
6
|
+
import { parseArgs, hasHelpFlag } from '../../lib/args-parser.js';
|
|
7
|
+
import { ImageGenerationService } from './service.js';
|
|
8
|
+
function showHelp() {
|
|
9
|
+
console.log(`
|
|
10
|
+
Generate AI Image
|
|
11
|
+
|
|
12
|
+
USAGE:
|
|
13
|
+
ecomcoder image generate --prompt=<description> [OPTIONS]
|
|
14
|
+
|
|
15
|
+
REQUIRED OPTIONS:
|
|
16
|
+
--prompt <text> Description of image to generate
|
|
17
|
+
|
|
18
|
+
OPTIONAL OPTIONS:
|
|
19
|
+
--size <size> Image size (default: 1024x1024)
|
|
20
|
+
Options: 1024x1024, 1792x1024, 1024x1792
|
|
21
|
+
--quality <quality> Image quality (default: standard)
|
|
22
|
+
Options: standard, hd
|
|
23
|
+
--style <style> Image style (default: vivid)
|
|
24
|
+
Options: vivid, natural
|
|
25
|
+
--session-id <id> Session ID (auto-provided by AI agent)
|
|
26
|
+
--backend-url <url> Backend URL override
|
|
27
|
+
--jwt <token> JWT token override
|
|
28
|
+
--help, -h Show this help
|
|
29
|
+
|
|
30
|
+
EXAMPLES:
|
|
31
|
+
# Generate hero banner
|
|
32
|
+
ecomcoder image generate --prompt="Tropical beach sunset with palm trees"
|
|
33
|
+
|
|
34
|
+
# Generate with specific size and quality
|
|
35
|
+
ecomcoder image generate \\
|
|
36
|
+
--prompt="Modern minimalist product photo" \\
|
|
37
|
+
--size=1792x1024 \\
|
|
38
|
+
--quality=hd
|
|
39
|
+
|
|
40
|
+
# Generate lifestyle photo
|
|
41
|
+
ecomcoder image generate \\
|
|
42
|
+
--prompt="Woman using skincare product in bathroom" \\
|
|
43
|
+
--style=natural
|
|
44
|
+
|
|
45
|
+
SETUP:
|
|
46
|
+
Set environment variable: OPENAI_API_KEY=sk-proj-...
|
|
47
|
+
|
|
48
|
+
NOTES:
|
|
49
|
+
- Generated images are automatically uploaded to Shopify
|
|
50
|
+
- Returns permanent Shopify CDN URL
|
|
51
|
+
- AI may revise your prompt for safety/quality
|
|
52
|
+
- Standard quality: ~15s generation time
|
|
53
|
+
- HD quality: ~20s generation time
|
|
54
|
+
|
|
55
|
+
OUTPUT:
|
|
56
|
+
{
|
|
57
|
+
"success": true,
|
|
58
|
+
"data": {
|
|
59
|
+
"asset": {
|
|
60
|
+
"shopifyUrl": "https://cdn.shopify.com/...",
|
|
61
|
+
"alt": "AI-revised description",
|
|
62
|
+
"originalPrompt": "Your original prompt",
|
|
63
|
+
"revisedPrompt": "AI-improved prompt"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
70
|
+
export async function run(argv = process.argv.slice(2)) {
|
|
71
|
+
if (hasHelpFlag(argv)) {
|
|
72
|
+
showHelp();
|
|
73
|
+
}
|
|
74
|
+
const args = parseArgs(argv);
|
|
75
|
+
// Validate required arguments
|
|
76
|
+
if (!args.prompt) {
|
|
77
|
+
console.error(JSON.stringify({
|
|
78
|
+
success: false,
|
|
79
|
+
error: 'Missing required argument: --prompt'
|
|
80
|
+
}));
|
|
81
|
+
process.exit(1);
|
|
82
|
+
}
|
|
83
|
+
// Validate size
|
|
84
|
+
const validSizes = ['1024x1024', '1792x1024', '1024x1792'];
|
|
85
|
+
if (args.size && !validSizes.includes(args.size)) {
|
|
86
|
+
console.error(JSON.stringify({
|
|
87
|
+
success: false,
|
|
88
|
+
error: `Invalid --size. Must be one of: ${validSizes.join(', ')}`
|
|
89
|
+
}));
|
|
90
|
+
process.exit(1);
|
|
91
|
+
}
|
|
92
|
+
// Validate quality
|
|
93
|
+
const validQualities = ['standard', 'hd'];
|
|
94
|
+
if (args.quality && !validQualities.includes(args.quality)) {
|
|
95
|
+
console.error(JSON.stringify({
|
|
96
|
+
success: false,
|
|
97
|
+
error: `Invalid --quality. Must be one of: ${validQualities.join(', ')}`
|
|
98
|
+
}));
|
|
99
|
+
process.exit(1);
|
|
100
|
+
}
|
|
101
|
+
// Validate style
|
|
102
|
+
const validStyles = ['vivid', 'natural'];
|
|
103
|
+
if (args.style && !validStyles.includes(args.style)) {
|
|
104
|
+
console.error(JSON.stringify({
|
|
105
|
+
success: false,
|
|
106
|
+
error: `Invalid --style. Must be one of: ${validStyles.join(', ')}`
|
|
107
|
+
}));
|
|
108
|
+
process.exit(1);
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
// Get credentials and session ID
|
|
112
|
+
const sessionId = getSessionId(args.sessionId);
|
|
113
|
+
const credentials = await getCredentials(sessionId, args.backendUrl, args.jwt);
|
|
114
|
+
// Generate and upload image
|
|
115
|
+
const result = await ImageGenerationService.generate(credentials, {
|
|
116
|
+
prompt: args.prompt,
|
|
117
|
+
size: args.size,
|
|
118
|
+
quality: args.quality,
|
|
119
|
+
style: args.style,
|
|
120
|
+
sessionId
|
|
121
|
+
});
|
|
122
|
+
console.log(JSON.stringify(result, null, 2));
|
|
123
|
+
if (!result.success) {
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
console.error(JSON.stringify({
|
|
129
|
+
success: false,
|
|
130
|
+
error: error.message || 'Unknown error occurred'
|
|
131
|
+
}));
|
|
132
|
+
process.exit(1);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
//# sourceMappingURL=generate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generate.js","sourceRoot":"","sources":["../../../src/commands/image/generate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/image/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAgB,qBAAqB,IAAI,IAAI,CAmB5C"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Command Registration
|
|
3
|
+
*/
|
|
4
|
+
import { registry } from '../../lib/command-registry.js';
|
|
5
|
+
import { HelpGenerator } from '../../lib/help-generator.js';
|
|
6
|
+
export function registerImageCommands() {
|
|
7
|
+
// Register group
|
|
8
|
+
registry.registerGroup({
|
|
9
|
+
command: 'image',
|
|
10
|
+
description: 'AI image generation and management',
|
|
11
|
+
showHelp: () => {
|
|
12
|
+
console.log(HelpGenerator.generateGroupHelp('image'));
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
// Register generate command
|
|
16
|
+
registry.register({
|
|
17
|
+
command: 'image',
|
|
18
|
+
subcommand: 'generate',
|
|
19
|
+
description: 'Generate AI image using DALL-E 3',
|
|
20
|
+
category: 'Create',
|
|
21
|
+
quickExample: 'ecomcoder image generate --prompt="tropical sunset"',
|
|
22
|
+
handler: async () => await import('./generate.js')
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/image/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,oCAAoC;QACjD,QAAQ,EAAE,GAAG,EAAE;YACb,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;QACxD,CAAC;KACF,CAAC,CAAC;IAEH,4BAA4B;IAC5B,QAAQ,CAAC,QAAQ,CAAC;QAChB,OAAO,EAAE,OAAO;QAChB,UAAU,EAAE,UAAU;QACtB,WAAW,EAAE,kCAAkC;QAC/C,QAAQ,EAAE,QAAQ;QAClB,YAAY,EAAE,qDAAqD;QACnE,OAAO,EAAE,KAAK,IAAI,EAAE,CAAC,MAAM,MAAM,CAAC,eAAe,CAAC;KACnD,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI DALL-E 3 Integration
|
|
3
|
+
* Handles image generation via OpenAI API
|
|
4
|
+
*/
|
|
5
|
+
export interface GenerateImageInput {
|
|
6
|
+
prompt: string;
|
|
7
|
+
size?: '1024x1024' | '1792x1024' | '1024x1792';
|
|
8
|
+
quality?: 'standard' | 'hd';
|
|
9
|
+
style?: 'vivid' | 'natural';
|
|
10
|
+
}
|
|
11
|
+
export interface GeneratedImage {
|
|
12
|
+
url: string;
|
|
13
|
+
revisedPrompt: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Generate image using OpenAI DALL-E 3
|
|
17
|
+
*/
|
|
18
|
+
export declare function generateImage(input: GenerateImageInput): Promise<GeneratedImage>;
|
|
19
|
+
//# sourceMappingURL=openai.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.d.ts","sourceRoot":"","sources":["../../../src/commands/image/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,WAAW,GAAG,WAAW,GAAG,WAAW,CAAC;IAC/C,OAAO,CAAC,EAAE,UAAU,GAAG,IAAI,CAAC;IAC5B,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC7B;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAC;IACZ,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,cAAc,CAAC,CAgCtF"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAI DALL-E 3 Integration
|
|
3
|
+
* Handles image generation via OpenAI API
|
|
4
|
+
*/
|
|
5
|
+
import OpenAI from 'openai';
|
|
6
|
+
/**
|
|
7
|
+
* Generate image using OpenAI DALL-E 3
|
|
8
|
+
*/
|
|
9
|
+
export async function generateImage(input) {
|
|
10
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
11
|
+
if (!apiKey) {
|
|
12
|
+
throw new Error('OPENAI_API_KEY environment variable not set');
|
|
13
|
+
}
|
|
14
|
+
const openai = new OpenAI({ apiKey });
|
|
15
|
+
const response = await openai.images.generate({
|
|
16
|
+
model: 'dall-e-3',
|
|
17
|
+
prompt: input.prompt,
|
|
18
|
+
n: 1,
|
|
19
|
+
size: input.size || '1024x1024',
|
|
20
|
+
quality: input.quality || 'standard',
|
|
21
|
+
style: input.style || 'vivid'
|
|
22
|
+
});
|
|
23
|
+
if (!response.data || response.data.length === 0) {
|
|
24
|
+
throw new Error('No images returned from OpenAI');
|
|
25
|
+
}
|
|
26
|
+
const imageData = response.data[0];
|
|
27
|
+
if (!imageData || !imageData.url) {
|
|
28
|
+
throw new Error('No image returned from OpenAI');
|
|
29
|
+
}
|
|
30
|
+
return {
|
|
31
|
+
url: imageData.url,
|
|
32
|
+
revisedPrompt: imageData.revised_prompt || input.prompt
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=openai.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../../src/commands/image/openai.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,MAAM,MAAM,QAAQ,CAAC;AAc5B;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,KAAyB;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;IAE1C,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjE,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IAEtC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;QAC5C,KAAK,EAAE,UAAU;QACjB,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,CAAC,EAAE,CAAC;QACJ,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,WAAW;QAC/B,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,UAAU;QACpC,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,OAAO;KAC9B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAEnC,IAAI,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,OAAO;QACL,GAAG,EAAE,SAAS,CAAC,GAAG;QAClB,aAAa,EAAE,SAAS,CAAC,cAAc,IAAI,KAAK,CAAC,MAAM;KACxD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Generation Service
|
|
3
|
+
* Orchestrates: OpenAI generation → Download → Shopify upload
|
|
4
|
+
*/
|
|
5
|
+
import { ShopifyCredentials, CommandResult } from '../../lib/types.js';
|
|
6
|
+
import { GenerateImageInput } from './openai.js';
|
|
7
|
+
export interface ImageGenerationInput extends GenerateImageInput {
|
|
8
|
+
sessionId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface GeneratedAsset {
|
|
11
|
+
id: string;
|
|
12
|
+
shopifyUrl: string;
|
|
13
|
+
alt: string;
|
|
14
|
+
originalPrompt: string;
|
|
15
|
+
revisedPrompt: string;
|
|
16
|
+
}
|
|
17
|
+
export declare class ImageGenerationService {
|
|
18
|
+
/**
|
|
19
|
+
* Generate image and upload to Shopify
|
|
20
|
+
*
|
|
21
|
+
* Flow:
|
|
22
|
+
* 1. Generate image via OpenAI DALL-E 3
|
|
23
|
+
* 2. Download from Azure blob (temporary URL)
|
|
24
|
+
* 3. Upload to Shopify Files
|
|
25
|
+
* 4. Return Shopify CDN URL
|
|
26
|
+
*/
|
|
27
|
+
static generate(credentials: ShopifyCredentials, input: ImageGenerationInput): Promise<CommandResult<{
|
|
28
|
+
asset: GeneratedAsset;
|
|
29
|
+
}>>;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/commands/image/service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAiB,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAIhE,MAAM,WAAW,oBAAqB,SAAQ,kBAAkB;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,sBAAsB;IACjC;;;;;;;;OAQG;WACU,QAAQ,CACnB,WAAW,EAAE,kBAAkB,EAC/B,KAAK,EAAE,oBAAoB,GAC1B,OAAO,CAAC,aAAa,CAAC;QAAE,KAAK,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC;CAyDrD"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Image Generation Service
|
|
3
|
+
* Orchestrates: OpenAI generation → Download → Shopify upload
|
|
4
|
+
*/
|
|
5
|
+
import { generateImage } from './openai.js';
|
|
6
|
+
import { AssetService } from '../asset/service.js';
|
|
7
|
+
import { downloadUrlToTemp } from '../asset/utils.js';
|
|
8
|
+
export class ImageGenerationService {
|
|
9
|
+
/**
|
|
10
|
+
* Generate image and upload to Shopify
|
|
11
|
+
*
|
|
12
|
+
* Flow:
|
|
13
|
+
* 1. Generate image via OpenAI DALL-E 3
|
|
14
|
+
* 2. Download from Azure blob (temporary URL)
|
|
15
|
+
* 3. Upload to Shopify Files
|
|
16
|
+
* 4. Return Shopify CDN URL
|
|
17
|
+
*/
|
|
18
|
+
static async generate(credentials, input) {
|
|
19
|
+
try {
|
|
20
|
+
// Step 1: Generate image via OpenAI
|
|
21
|
+
const generated = await generateImage({
|
|
22
|
+
prompt: input.prompt,
|
|
23
|
+
size: input.size,
|
|
24
|
+
quality: input.quality,
|
|
25
|
+
style: input.style
|
|
26
|
+
});
|
|
27
|
+
// Step 2: Download from Azure blob to temp file
|
|
28
|
+
const downloaded = await downloadUrlToTemp(generated.url);
|
|
29
|
+
try {
|
|
30
|
+
// Step 3: Upload to Shopify
|
|
31
|
+
// Truncate alt text to 512 characters (Shopify limit)
|
|
32
|
+
const altText = generated.revisedPrompt.length > 512
|
|
33
|
+
? generated.revisedPrompt.substring(0, 509) + '...'
|
|
34
|
+
: generated.revisedPrompt;
|
|
35
|
+
const uploadResult = await AssetService.upload(credentials, {
|
|
36
|
+
file: downloaded.path,
|
|
37
|
+
alt: altText,
|
|
38
|
+
contentType: 'IMAGE'
|
|
39
|
+
});
|
|
40
|
+
if (!uploadResult.success) {
|
|
41
|
+
throw new Error(uploadResult.error);
|
|
42
|
+
}
|
|
43
|
+
const asset = uploadResult.data.asset;
|
|
44
|
+
return {
|
|
45
|
+
success: true,
|
|
46
|
+
data: {
|
|
47
|
+
asset: {
|
|
48
|
+
id: asset.id,
|
|
49
|
+
shopifyUrl: asset.url,
|
|
50
|
+
alt: altText,
|
|
51
|
+
originalPrompt: input.prompt,
|
|
52
|
+
revisedPrompt: generated.revisedPrompt
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
// Step 4: Cleanup temp file
|
|
59
|
+
if (downloaded.cleanup) {
|
|
60
|
+
downloaded.cleanup();
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
return {
|
|
66
|
+
success: false,
|
|
67
|
+
error: error.message || 'Image generation failed'
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"service.js","sourceRoot":"","sources":["../../../src/commands/image/service.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,aAAa,EAAsB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AActD,MAAM,OAAO,sBAAsB;IACjC;;;;;;;;OAQG;IACH,MAAM,CAAC,KAAK,CAAC,QAAQ,CACnB,WAA+B,EAC/B,KAA2B;QAE3B,IAAI,CAAC;YACH,oCAAoC;YACpC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC;gBACpC,MAAM,EAAE,KAAK,CAAC,MAAM;gBACpB,IAAI,EAAE,KAAK,CAAC,IAAI;gBAChB,OAAO,EAAE,KAAK,CAAC,OAAO;gBACtB,KAAK,EAAE,KAAK,CAAC,KAAK;aACnB,CAAC,CAAC;YAEH,gDAAgD;YAChD,MAAM,UAAU,GAAG,MAAM,iBAAiB,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;YAE1D,IAAI,CAAC;gBACH,4BAA4B;gBAC5B,sDAAsD;gBACtD,MAAM,OAAO,GAAG,SAAS,CAAC,aAAa,CAAC,MAAM,GAAG,GAAG;oBAClD,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;oBACnD,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC;gBAE5B,MAAM,YAAY,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,WAAW,EAAE;oBAC1D,IAAI,EAAE,UAAU,CAAC,IAAI;oBACrB,GAAG,EAAE,OAAO;oBACZ,WAAW,EAAE,OAAO;iBACrB,CAAC,CAAC;gBAEH,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC;oBAC1B,MAAM,IAAI,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;gBACtC,CAAC;gBAED,MAAM,KAAK,GAAG,YAAY,CAAC,IAAK,CAAC,KAAK,CAAC;gBAEvC,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,IAAI,EAAE;wBACJ,KAAK,EAAE;4BACL,EAAE,EAAE,KAAK,CAAC,EAAE;4BACZ,UAAU,EAAE,KAAK,CAAC,GAAG;4BACrB,GAAG,EAAE,OAAO;4BACZ,cAAc,EAAE,KAAK,CAAC,MAAM;4BAC5B,aAAa,EAAE,SAAS,CAAC,aAAa;yBACvC;qBACF;iBACF,CAAC;YACJ,CAAC;oBAAS,CAAC;gBACT,4BAA4B;gBAC5B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;oBACvB,UAAU,CAAC,OAAO,EAAE,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE,KAAK;gBACd,KAAK,EAAE,KAAK,CAAC,OAAO,IAAI,yBAAyB;aAClD,CAAC;QACJ,CAAC;IACH,CAAC;CACF"}
|
package/dist/lib/approval.d.ts
CHANGED
|
@@ -17,12 +17,27 @@ export interface ApprovalResponse {
|
|
|
17
17
|
* Request approval from user (via ecomcoder-app)
|
|
18
18
|
*
|
|
19
19
|
* Protocol:
|
|
20
|
-
* 1. Check if
|
|
21
|
-
* 2.
|
|
22
|
-
* 3. If
|
|
20
|
+
* 1. Check if approvals are globally disabled via configuration
|
|
21
|
+
* 2. Check if APPROVAL_GRANTED=true env var is set (for testing)
|
|
22
|
+
* 3. If neither, output APPROVAL_REQUIRED JSON and exit
|
|
23
|
+
*
|
|
24
|
+
* Configuration priority:
|
|
25
|
+
* - REQUIRE_APPROVAL environment variable
|
|
26
|
+
* - .ecomcoder.json in current directory
|
|
27
|
+
* - .ecomcoder.json in home directory
|
|
28
|
+
* - Default (true)
|
|
23
29
|
*
|
|
24
30
|
* @param request - Approval request details
|
|
25
|
-
* @returns true if approved (only returns if pre-approved
|
|
31
|
+
* @returns true if approved (only returns if pre-approved)
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Disable approvals globally
|
|
35
|
+
* REQUIRE_APPROVAL=false ecomcoder product update-price --id=123 --price=29.99
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Disable approvals via config file
|
|
39
|
+
* echo '{"requireApproval": false}' > .ecomcoder.json
|
|
40
|
+
* ecomcoder product update-price --id=123 --price=29.99
|
|
26
41
|
*/
|
|
27
42
|
export declare function requestApproval(request: ApprovalRequest): Promise<boolean>;
|
|
28
43
|
//# sourceMappingURL=approval.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../../src/lib/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"approval.d.ts","sourceRoot":"","sources":["../../src/lib/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,UAAU,GAAG,MAAM,CAAC;CAChC;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC,CA4BhF"}
|
package/dist/lib/approval.js
CHANGED
|
@@ -5,19 +5,40 @@
|
|
|
5
5
|
* Communicates with ecomcoder-app via stdout/stdin
|
|
6
6
|
*/
|
|
7
7
|
import { randomUUID } from 'crypto';
|
|
8
|
+
import { getConfig } from './config.js';
|
|
8
9
|
/**
|
|
9
10
|
* Request approval from user (via ecomcoder-app)
|
|
10
11
|
*
|
|
11
12
|
* Protocol:
|
|
12
|
-
* 1. Check if
|
|
13
|
-
* 2.
|
|
14
|
-
* 3. If
|
|
13
|
+
* 1. Check if approvals are globally disabled via configuration
|
|
14
|
+
* 2. Check if APPROVAL_GRANTED=true env var is set (for testing)
|
|
15
|
+
* 3. If neither, output APPROVAL_REQUIRED JSON and exit
|
|
16
|
+
*
|
|
17
|
+
* Configuration priority:
|
|
18
|
+
* - REQUIRE_APPROVAL environment variable
|
|
19
|
+
* - .ecomcoder.json in current directory
|
|
20
|
+
* - .ecomcoder.json in home directory
|
|
21
|
+
* - Default (true)
|
|
15
22
|
*
|
|
16
23
|
* @param request - Approval request details
|
|
17
|
-
* @returns true if approved (only returns if pre-approved
|
|
24
|
+
* @returns true if approved (only returns if pre-approved)
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* // Disable approvals globally
|
|
28
|
+
* REQUIRE_APPROVAL=false ecomcoder product update-price --id=123 --price=29.99
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Disable approvals via config file
|
|
32
|
+
* echo '{"requireApproval": false}' > .ecomcoder.json
|
|
33
|
+
* ecomcoder product update-price --id=123 --price=29.99
|
|
18
34
|
*/
|
|
19
35
|
export async function requestApproval(request) {
|
|
20
|
-
// Check if
|
|
36
|
+
// Check if approvals are globally disabled
|
|
37
|
+
const config = getConfig();
|
|
38
|
+
if (!config.requireApproval) {
|
|
39
|
+
return true; // Auto-approve when disabled
|
|
40
|
+
}
|
|
41
|
+
// Check if approval was pre-granted via environment variable (for automated tests)
|
|
21
42
|
if (process.env.APPROVAL_GRANTED === 'true') {
|
|
22
43
|
return true;
|
|
23
44
|
}
|
package/dist/lib/approval.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/lib/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"approval.js","sourceRoot":"","sources":["../../src/lib/approval.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAaxC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,OAAwB;IAC5D,2CAA2C;IAC3C,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QAC5B,OAAO,IAAI,CAAC,CAAC,6BAA6B;IAC5C,CAAC;IAED,mFAAmF;IACnF,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAC5C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,MAAM,UAAU,GAAG,UAAU,EAAE,CAAC;IAEhC,yCAAyC;IACzC,MAAM,eAAe,GAAG;QACtB,IAAI,EAAE,mBAAmB;QACzB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,UAAU;QACV,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC;IAE7C,sFAAsF;IACtF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration Management
|
|
3
|
+
*
|
|
4
|
+
* Centralized configuration for CLI behavior
|
|
5
|
+
* Supports multiple configuration sources with priority order:
|
|
6
|
+
* 1. Environment variables (highest priority)
|
|
7
|
+
* 2. .ecomcoder.json in current directory
|
|
8
|
+
* 3. .ecomcoder.json in home directory
|
|
9
|
+
* 4. Default values (lowest priority)
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* CLI Configuration Interface
|
|
13
|
+
*/
|
|
14
|
+
export interface Config {
|
|
15
|
+
/**
|
|
16
|
+
* Whether to require user approval for destructive operations
|
|
17
|
+
* Set to true to enable approval prompts (useful for safety)
|
|
18
|
+
* @default false
|
|
19
|
+
*/
|
|
20
|
+
requireApproval: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Get current CLI configuration
|
|
24
|
+
*
|
|
25
|
+
* Priority order:
|
|
26
|
+
* 1. REQUIRE_APPROVAL environment variable
|
|
27
|
+
* 2. .ecomcoder.json in current working directory
|
|
28
|
+
* 3. .ecomcoder.json in home directory
|
|
29
|
+
* 4. Default values (requireApproval: false)
|
|
30
|
+
*
|
|
31
|
+
* @returns Current configuration
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* // Environment variable (highest priority)
|
|
35
|
+
* REQUIRE_APPROVAL=false ecomcoder product update-price --id=123 --price=29.99
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* // Project-specific config
|
|
39
|
+
* echo '{"requireApproval": false}' > .ecomcoder.json
|
|
40
|
+
* ecomcoder product update-price --id=123 --price=29.99
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* // Global user config
|
|
44
|
+
* echo '{"requireApproval": false}' > ~/.ecomcoder.json
|
|
45
|
+
* ecomcoder product update-price --id=123 --price=29.99
|
|
46
|
+
*/
|
|
47
|
+
export declare function getConfig(): Config;
|
|
48
|
+
/**
|
|
49
|
+
* Clear cached configuration (useful for testing)
|
|
50
|
+
*/
|
|
51
|
+
export declare function clearConfigCache(): void;
|
|
52
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH;;GAEG;AACH,MAAM,WAAW,MAAM;IACrB;;;;OAIG;IACH,eAAe,EAAE,OAAO,CAAC;CAC1B;AAWD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAsClC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC"}
|