@dk/jolly 0.1.8 → 0.1.10

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 (49) hide show
  1. package/README.md +16 -92
  2. package/bin/jolly +2 -0
  3. package/package.json +27 -24
  4. package/src/index.ts +2095 -0
  5. package/src/lib/cloud-api.ts +527 -0
  6. package/src/lib/env-file.ts +68 -0
  7. package/src/lib/saleor-url.ts +37 -0
  8. package/.env.example +0 -3
  9. package/.mcp.json +0 -7
  10. package/.sisyphus/boulder.json +0 -13
  11. package/.sisyphus/notepads/saleor-agent-cli/decisions.md +0 -11
  12. package/.sisyphus/notepads/saleor-agent-cli/issues.md +0 -6
  13. package/.sisyphus/notepads/saleor-agent-cli/learnings.md +0 -6
  14. package/.sisyphus/plans/saleor-agent-cli.md +0 -600
  15. package/AGENTS.md +0 -46
  16. package/bun.lock +0 -123
  17. package/bunfig.toml +0 -8
  18. package/dist/agent.js +0 -258
  19. package/dist/bootstrap.js +0 -184
  20. package/dist/index.js +0 -722
  21. package/src/agents/index.ts +0 -1
  22. package/src/agents/setup.ts +0 -210
  23. package/src/api/auth.ts +0 -75
  24. package/src/api/client.ts +0 -152
  25. package/src/api/endpoints.ts +0 -8
  26. package/src/api/index.ts +0 -4
  27. package/src/cli/agent.ts +0 -26
  28. package/src/cli/bootstrap.ts +0 -24
  29. package/src/cli/commands/agent.ts +0 -40
  30. package/src/cli/commands/app.ts +0 -61
  31. package/src/cli/commands/config.ts +0 -38
  32. package/src/cli/commands/store.ts +0 -75
  33. package/src/cli/index.ts +0 -16
  34. package/src/commands/app.ts +0 -126
  35. package/src/commands/index.ts +0 -1
  36. package/src/commands/store.ts +0 -64
  37. package/src/test/command-handlers.test.ts +0 -232
  38. package/src/test/e2e-flows.test.ts +0 -231
  39. package/src/test/entry-points.test.ts +0 -126
  40. package/src/test/error-handling.test.ts +0 -137
  41. package/src/test/helpers.ts +0 -49
  42. package/src/test/index.ts +0 -1
  43. package/src/test/mocks.ts +0 -172
  44. package/src/test/setup.ts +0 -29
  45. package/src/tui/components.ts +0 -77
  46. package/src/tui/index.ts +0 -3
  47. package/src/tui/renderer.ts +0 -34
  48. package/src/tui/theme.ts +0 -38
  49. package/tsconfig.json +0 -20
package/dist/index.js DELETED
@@ -1,722 +0,0 @@
1
- #!/usr/bin/env node
2
- import { createRequire } from "node:module";
3
- var __create = Object.create;
4
- var __getProtoOf = Object.getPrototypeOf;
5
- var __defProp = Object.defineProperty;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __toESM = (mod, isNodeMode, target) => {
9
- target = mod != null ? __create(__getProtoOf(mod)) : {};
10
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
- for (let key of __getOwnPropNames(mod))
12
- if (!__hasOwnProp.call(to, key))
13
- __defProp(to, key, {
14
- get: () => mod[key],
15
- enumerable: true
16
- });
17
- return to;
18
- };
19
- var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
-
21
- // src/cli/index.ts
22
- import yargs from "yargs";
23
- import { hideBin } from "yargs/helpers";
24
-
25
- // src/api/client.ts
26
- class SaleorCloudClient {
27
- baseUrl = "https://cloud.saleor.io/api/v1";
28
- token;
29
- constructor(token) {
30
- this.token = token || process.env.SALEOR_CLOUD_TOKEN || "";
31
- if (!this.token) {
32
- throw new Error("SALEOR_CLOUD_TOKEN environment variable is required");
33
- }
34
- }
35
- async request(endpoint, options) {
36
- const mergedOptions = {
37
- method: options?.method || "GET",
38
- ...options,
39
- headers: {
40
- Authorization: `Token ${this.token}`,
41
- "Content-Type": "application/json",
42
- ...options?.headers
43
- }
44
- };
45
- const response = await fetch(`${this.baseUrl}${endpoint}`, mergedOptions);
46
- if (!response.ok) {
47
- const body = await response.text();
48
- const truncatedBody = body.length > 200 ? body.substring(0, 200) + "..." : body;
49
- throw new Error(`API error: ${response.status} ${response.statusText} - ${truncatedBody}`);
50
- }
51
- return response.json();
52
- }
53
- async getOrganizations() {
54
- return this.request("/organizations");
55
- }
56
- async getProjects(organizationSlug) {
57
- return this.request(`/organizations/${organizationSlug}/projects`);
58
- }
59
- async createProject(organizationSlug, name, region) {
60
- return this.request(`/organizations/${organizationSlug}/projects`, {
61
- method: "POST",
62
- body: JSON.stringify({ name, region })
63
- });
64
- }
65
- async getEnvironments(organizationSlug, projectSlug) {
66
- return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments`);
67
- }
68
- async createEnvironment(organizationSlug, projectSlug, name, region) {
69
- return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments`, {
70
- method: "POST",
71
- body: JSON.stringify({ name, region })
72
- });
73
- }
74
- async getEnvironment(organizationSlug, projectSlug, environmentSlug) {
75
- return this.request(`/organizations/${organizationSlug}/projects/${projectSlug}/environments/${environmentSlug}`);
76
- }
77
- async registerApp(environmentId, appType, name) {
78
- return this.request(`/environments/${environmentId}/apps`, {
79
- method: "POST",
80
- body: JSON.stringify({ type: appType, name })
81
- });
82
- }
83
- async getStores() {
84
- return this.getOrganizations();
85
- }
86
- async createStore(name, region = "us-east-1") {
87
- const { organizations } = await this.getOrganizations();
88
- if (organizations.length === 0) {
89
- throw new Error("No organizations found. Create one at https://cloud.saleor.io");
90
- }
91
- return this.createProject(organizations[0].slug, name, region);
92
- }
93
- async createEnvironmentFromStore(storeId, name) {
94
- const { environments } = await this.getEnvironments(storeId, "default");
95
- return this.createEnvironment(storeId, environments.length > 0 ? environments[0].project?.slug || "default" : "default", name, "default");
96
- }
97
- }
98
-
99
- // src/api/auth.ts
100
- import { config } from "@dotenvx/dotenvx";
101
- import { writeFileSync, existsSync, readFileSync } from "fs";
102
- import { join } from "path";
103
- config();
104
- function requireToken() {
105
- const token = process.env.SALEOR_CLOUD_TOKEN;
106
- if (!token) {
107
- console.error(`
108
- \uD83D\uDD11 Saleor Cloud Token Required`);
109
- console.error(` Get your token at: https://cloud.saleor.io/settings/api-tokens
110
- `);
111
- console.error("Or create a .env file with: SALEOR_CLOUD_TOKEN=your-token");
112
- console.error(`
113
- To set token: export SALEOR_CLOUD_TOKEN=your-token
114
- `);
115
- process.exit(1);
116
- }
117
- return token;
118
- }
119
- async function promptAndSaveToken() {
120
- console.log(`
121
- \uD83D\uDD11 Saleor Cloud Token Required`);
122
- console.log(` Get your token at: https://cloud.saleor.io/settings/api-tokens
123
- `);
124
- const readline = await import("readline");
125
- const rl = readline.createInterface({
126
- input: process.stdin,
127
- output: process.stdout
128
- });
129
- return new Promise((resolve) => {
130
- rl.question("Enter your SALEOR_CLOUD_TOKEN: ", (answer) => {
131
- rl.close();
132
- const token = answer.trim();
133
- if (!token) {
134
- console.error("Error: Token cannot be empty");
135
- process.exit(1);
136
- }
137
- const envPath = join(process.cwd(), ".env");
138
- const envLine = `SALEOR_CLOUD_TOKEN=${token}
139
- `;
140
- try {
141
- let existingContent = "";
142
- if (existsSync(envPath)) {
143
- existingContent = readFileSync(envPath, "utf-8");
144
- if (existingContent.includes("SALEOR_CLOUD_TOKEN=")) {
145
- existingContent = existingContent.replace(/SALEOR_CLOUD_TOKEN=.*\n?/g, envLine);
146
- } else {
147
- existingContent += envLine;
148
- }
149
- } else {
150
- existingContent = envLine;
151
- }
152
- writeFileSync(envPath, existingContent);
153
- console.log(`
154
- ✅ Token saved to .env file`);
155
- } catch {
156
- console.log(`
157
- ⚠️ Could not save to .env, token will not persist`);
158
- }
159
- process.env.SALEOR_CLOUD_TOKEN = token;
160
- resolve(token);
161
- });
162
- });
163
- }
164
-
165
- // src/tui/theme.ts
166
- var theme = {
167
- reset: "\x1B[0m",
168
- bold: "\x1B[1m",
169
- dim: "\x1B[2m",
170
- italic: "\x1B[3m",
171
- underline: "\x1B[4m",
172
- fg: {
173
- black: "\x1B[30m",
174
- red: "\x1B[31m",
175
- green: "\x1B[32m",
176
- yellow: "\x1B[33m",
177
- blue: "\x1B[34m",
178
- magenta: "\x1B[35m",
179
- cyan: "\x1B[36m",
180
- white: "\x1B[37m",
181
- gray: "\x1B[90m",
182
- brightBlack: "\x1B[30;1m",
183
- brightRed: "\x1B[31;1m",
184
- brightGreen: "\x1B[32;1m",
185
- brightYellow: "\x1B[33;1m",
186
- brightBlue: "\x1B[34;1m",
187
- brightMagenta: "\x1B[35;1m",
188
- brightCyan: "\x1B[36;1m",
189
- brightWhite: "\x1B[37;1m"
190
- },
191
- bg: {
192
- black: "\x1B[40m",
193
- red: "\x1B[41m",
194
- green: "\x1B[42m",
195
- yellow: "\x1B[43m",
196
- blue: "\x1B[44m",
197
- magenta: "\x1B[45m",
198
- cyan: "\x1B[46m",
199
- white: "\x1B[47m"
200
- }
201
- };
202
-
203
- // src/tui/components.ts
204
- function text(content, color) {
205
- return `${color || theme.fg.white}${content}${theme.reset}`;
206
- }
207
- function success(msg) {
208
- return text(msg, theme.fg.green);
209
- }
210
- function error(msg) {
211
- return text(msg, theme.fg.red);
212
- }
213
- function info(msg) {
214
- return text(msg, theme.fg.cyan);
215
- }
216
-
217
- // src/commands/store.ts
218
- async function createStore(name, region) {
219
- const token = requireToken();
220
- const client = new SaleorCloudClient(token);
221
- console.log(info(`Creating store: ${name} in ${region}...`));
222
- try {
223
- const result = await client.createStore(name, region);
224
- console.log(success(`Store created successfully!`));
225
- console.log(info(`Project slug: ${result.project.slug}`));
226
- console.log(info(`Dashboard: https://cloud.saleor.io/organizations/default/projects/${result.project.slug}`));
227
- } catch (err) {
228
- console.log(error(`Failed to create store: ${err}`));
229
- process.exit(1);
230
- }
231
- }
232
- async function listStores() {
233
- const token = requireToken();
234
- const client = new SaleorCloudClient(token);
235
- console.log(info("Fetching organizations..."));
236
- try {
237
- const { organizations } = await client.getOrganizations();
238
- if (organizations.length === 0) {
239
- console.log(info("No organizations found. Create one at https://cloud.saleor.io"));
240
- return;
241
- }
242
- console.log(success(`Found ${organizations.length} organization(s):
243
- `));
244
- for (const org of organizations) {
245
- console.log(` ${org.name} (${org.slug})`);
246
- console.log(` Email: ${org.owner_email}`);
247
- console.log(` Created: ${new Date(org.created).toLocaleDateString()}`);
248
- console.log();
249
- }
250
- } catch (err) {
251
- console.log(error(`Failed to list stores: ${err}`));
252
- process.exit(1);
253
- }
254
- }
255
- async function createEnvironment(organizationSlug, name) {
256
- const token = requireToken();
257
- const client = new SaleorCloudClient(token);
258
- console.log(info(`Creating environment: ${name} for organization ${organizationSlug}...`));
259
- try {
260
- const { environment } = await client.createEnvironment(organizationSlug, "default", name, "us-east-1");
261
- console.log(success(`Environment created successfully!`));
262
- console.log(info(`Environment key: ${environment.key}`));
263
- console.log(info(`Domain: ${environment.domain}`));
264
- } catch (err) {
265
- console.log(error(`Failed to create environment: ${err}`));
266
- process.exit(1);
267
- }
268
- }
269
-
270
- // src/cli/commands/store.ts
271
- async function ensureToken() {
272
- if (!process.env.SALEOR_CLOUD_TOKEN) {
273
- await promptAndSaveToken();
274
- }
275
- }
276
- var storeCommands = {
277
- command: "store <action>",
278
- describe: "Manage Saleor Cloud stores",
279
- builder: (yargs) => yargs.command({
280
- command: "create",
281
- describe: "Create a new Saleor Cloud store",
282
- builder: (yargs2) => yargs2.option("name", {
283
- alias: "n",
284
- type: "string",
285
- description: "Store name",
286
- demandOption: true
287
- }).option("region", {
288
- alias: "r",
289
- type: "string",
290
- description: "Region (e.g., us-east-1)",
291
- default: "us-east-1"
292
- }),
293
- handler: async (argv) => {
294
- await ensureToken();
295
- await createStore(argv.name, argv.region);
296
- }
297
- }).command({
298
- command: "list",
299
- describe: "List your Saleor Cloud stores",
300
- builder: (yargs2) => yargs2,
301
- handler: async () => {
302
- await ensureToken();
303
- await listStores();
304
- }
305
- }).command({
306
- command: "env <action>",
307
- describe: "Manage store environments",
308
- builder: (yargs2) => yargs2.command({
309
- command: "create",
310
- describe: "Create a new environment",
311
- builder: (yargs3) => yargs3.option("store", {
312
- alias: "s",
313
- type: "string",
314
- description: "Store ID",
315
- demandOption: true
316
- }).option("name", {
317
- alias: "n",
318
- type: "string",
319
- description: "Environment name",
320
- demandOption: true
321
- }),
322
- handler: async (argv) => {
323
- await ensureToken();
324
- await createEnvironment(argv.store, argv.name);
325
- }
326
- })
327
- })
328
- };
329
-
330
- // src/commands/app.ts
331
- var APP_TEMPLATES = {
332
- "dashboard-extension": {
333
- repo: "https://github.com/saleor/saleor-app-sdk",
334
- description: "Dashboard Extension App"
335
- },
336
- payment: {
337
- repo: "https://github.com/saleor/saleor-apps",
338
- description: "Payment App"
339
- },
340
- webhook: {
341
- repo: "https://github.com/saleor/saleor-webhook-template",
342
- description: "Webhook Handler"
343
- }
344
- };
345
- var PAYMENT_APP_URLS = {
346
- dummy: "https://dummy-payment.saleor.io",
347
- stripe: "https://stripe-payment.saleor.io"
348
- };
349
- async function createApp(name, type, environmentId, provider) {
350
- console.log(info(`Creating ${type} app: ${name}`));
351
- if (type === "payment") {
352
- const paymentProvider = provider || "dummy";
353
- console.log(info(`Payment provider: ${paymentProvider}`));
354
- console.log(info(`Using hosted payment app: ${PAYMENT_APP_URLS[paymentProvider]}`));
355
- if (environmentId) {
356
- await registerHostedApp(environmentId, name, paymentProvider);
357
- } else {
358
- console.log(success(`
359
- Payment app "${name}" configured to use ${PAYMENT_APP_URLS[paymentProvider]}`));
360
- console.log(info(`
361
- To complete setup:`));
362
- console.log(info(`1. Go to your dashboard at https://cloud.saleor.io`));
363
- console.log(info(`2. Navigate to Apps > Third party apps`));
364
- console.log(info(`3. Add the ${paymentProvider} payment app from ${PAYMENT_APP_URLS[paymentProvider]}`));
365
- }
366
- return;
367
- }
368
- const template = APP_TEMPLATES[type];
369
- console.log(info(`Cloning template from: ${template.repo}`));
370
- try {
371
- const { spawn } = await import("child_process");
372
- const child = spawn("git", ["clone", template.repo, name], {
373
- stdio: "inherit"
374
- });
375
- child.on("close", (code) => {
376
- if (code === 0) {
377
- console.log(success(`
378
- ${type} app "${name}" created successfully!`));
379
- console.log(info(`
380
- To get started:`));
381
- console.log(info(`cd ${name}`));
382
- console.log(info(`npm install`));
383
- console.log(info(`npm run dev`));
384
- if (environmentId) {
385
- console.log(info(`
386
- Registering app with environment ${environmentId}...`));
387
- registerLocalApp(environmentId, name, type);
388
- }
389
- } else {
390
- console.log(error(`Failed to clone template (exit code: ${code})`));
391
- process.exit(1);
392
- }
393
- });
394
- } catch (err) {
395
- console.log(error(`Failed to create app: ${err}`));
396
- process.exit(1);
397
- }
398
- }
399
- async function registerHostedApp(environmentId, name, provider) {
400
- const token = requireToken();
401
- const client = new SaleorCloudClient(token);
402
- console.log(info(`Registering hosted ${provider} payment app with environment...`));
403
- try {
404
- const result = await client.registerApp(environmentId, "payment", name);
405
- console.log(success(`Payment app registered successfully!`));
406
- console.log(info(`App ID: ${result.app.id}`));
407
- console.log(info(`Payment URL: ${PAYMENT_APP_URLS[provider]}`));
408
- } catch (err) {
409
- console.log(error(`Failed to register app: ${err}`));
410
- process.exit(1);
411
- }
412
- }
413
- async function registerLocalApp(environmentId, name, type) {
414
- const token = requireToken();
415
- const client = new SaleorCloudClient(token);
416
- try {
417
- const result = await client.registerApp(environmentId, type, name);
418
- console.log(success(`App registered with environment!`));
419
- console.log(info(`App ID: ${result.app.id}`));
420
- } catch (err) {
421
- console.log(warning(`Could not register app automatically: ${err}`));
422
- console.log(info(`You can register manually in the dashboard.`));
423
- }
424
- }
425
- function warning(msg) {
426
- console.log(`\x1B[33m${msg}\x1B[0m`);
427
- }
428
-
429
- // src/cli/commands/app.ts
430
- async function ensureToken2() {
431
- if (!process.env.SALEOR_CLOUD_TOKEN) {
432
- await promptAndSaveToken();
433
- }
434
- }
435
- var appCommands = {
436
- command: "app <action>",
437
- describe: "Scaffold Saleor apps",
438
- builder: (yargs) => yargs.command({
439
- command: "create",
440
- describe: "Create a new Saleor app",
441
- builder: (yargs2) => yargs2.option("name", {
442
- alias: "n",
443
- type: "string",
444
- description: "App name",
445
- demandOption: true
446
- }).option("type", {
447
- alias: "t",
448
- type: "string",
449
- choices: ["dashboard-extension", "payment", "webhook"],
450
- description: "App type",
451
- demandOption: true
452
- }).option("provider", {
453
- alias: "p",
454
- type: "string",
455
- choices: ["dummy", "stripe"],
456
- description: "Payment provider (for payment apps)",
457
- default: "dummy"
458
- }).option("environment", {
459
- alias: "e",
460
- type: "string",
461
- description: "Environment ID to register app with"
462
- }),
463
- handler: async (argv) => {
464
- if (argv.environment) {
465
- await ensureToken2();
466
- }
467
- await createApp(argv.name, argv.type, argv.environment, argv.provider);
468
- }
469
- })
470
- };
471
-
472
- // src/agents/setup.ts
473
- import { writeFileSync as writeFileSync2, mkdirSync, existsSync as existsSync2 } from "fs";
474
- import { spawnSync } from "child_process";
475
- import { join as join2 } from "path";
476
- var AGENT_PATHS = {
477
- opencode: {
478
- skills: ".agents/skills",
479
- agentsMd: "AGENTS.md",
480
- mcpJson: ".mcp.json"
481
- },
482
- claude: {
483
- skills: ".claude/skills",
484
- agentsMd: "CLAUDE.md",
485
- mcpJson: ".mcp.json"
486
- },
487
- openclaw: {
488
- skills: ".openclaw/skills",
489
- agentsMd: "AGENTS.md",
490
- mcpJson: ".mcp.json"
491
- },
492
- nanobot: {
493
- skills: ".nanobot/skills",
494
- agentsMd: "AGENTS.md",
495
- mcpJson: ".mcp.json"
496
- }
497
- };
498
- var SKILLS = [
499
- "saleor-app",
500
- "saleor-configurator",
501
- "saleor-core",
502
- "saleor-storefront"
503
- ];
504
- async function setupAgent(projectPath = ".") {
505
- info("Detecting AI agents...");
506
- const detectedAgents = detectAgents(projectPath);
507
- if (detectedAgents.length === 0) {
508
- info("No AI agents detected. Installing skills anyway...");
509
- installSkills(projectPath, "opencode");
510
- createAgentsMd(projectPath);
511
- createMcpConfig(projectPath);
512
- return;
513
- }
514
- info(`Detected agents: ${detectedAgents.map((a) => a.name).join(", ")}
515
- `);
516
- for (const agent of detectedAgents) {
517
- info(`Configuring ${agent.name}...`);
518
- installSkills(projectPath, agent.name);
519
- createAgentsMd(projectPath, agent.name);
520
- createMcpConfig(projectPath);
521
- success(` ${agent.name} configured!`);
522
- }
523
- success(`
524
- Agent setup complete!`);
525
- info(`
526
- Skills installed: ` + SKILLS.join(", "));
527
- info("AGENTS.md created with Saleor conventions");
528
- info(".mcp.json configured for saleor-mcp");
529
- }
530
- async function installSkillsCommand(projectPath = ".") {
531
- info("Installing Saleor agent skills...");
532
- info("Skills: " + SKILLS.join(", "));
533
- const detectedAgents = detectAgents(projectPath);
534
- if (detectedAgents.length === 0) {
535
- installSkills(projectPath, "opencode");
536
- } else {
537
- for (const agent of detectedAgents) {
538
- installSkills(projectPath, agent.name);
539
- }
540
- }
541
- success(`
542
- Skills installed successfully!`);
543
- }
544
- function detectAgents(projectPath) {
545
- const detected = [];
546
- const filesToCheck = [
547
- { name: "opencode", file: ".agents/skills" },
548
- { name: "claude", file: ".claude" },
549
- { name: "openclaw", file: ".openclaw" },
550
- { name: "nanobot", file: ".nanobot" }
551
- ];
552
- for (const { name, file } of filesToCheck) {
553
- const fullPath = join2(projectPath, file);
554
- if (existsSync2(fullPath)) {
555
- detected.push({
556
- name,
557
- path: fullPath,
558
- skillsPath: join2(fullPath, "skills")
559
- });
560
- }
561
- }
562
- return detected;
563
- }
564
- function installSkills(projectPath, agentName) {
565
- const agentPaths = AGENT_PATHS[agentName];
566
- const skillsDir = join2(projectPath, agentPaths.skills);
567
- mkdirSync(skillsDir, { recursive: true });
568
- info(` Installing skills to ${skillsDir}...`);
569
- const skillUrl = "https://github.com/saleor/agent-skills";
570
- const baseDir = join2(skillsDir, "..");
571
- try {
572
- const result = spawnSync("git", ["clone", "--depth", "1", skillUrl, "skills"], {
573
- cwd: baseDir,
574
- stdio: "pipe"
575
- });
576
- if (result.status === 0) {
577
- for (const skill of SKILLS) {
578
- info(` Installed ${skill}`);
579
- }
580
- success(` Skills installed to ${skillsDir}`);
581
- } else {
582
- info(` Could not clone skills, skipping...`);
583
- }
584
- } catch {
585
- info(` Could not clone skills, skipping...`);
586
- }
587
- }
588
- function createAgentsMd(projectPath, agentName = "opencode") {
589
- const agentsMdContent = `# Saleor Development Guide
590
-
591
- This project uses Saleor e-commerce platform.
592
-
593
- ## Commands
594
-
595
- \`\`\`bash
596
- # Development
597
- npm run dev
598
-
599
- # Build
600
- npm run build
601
-
602
- # Test
603
- npm run test
604
-
605
- # Lint
606
- npm run lint
607
- \`\`\`
608
-
609
- ## Saleor Cloud
610
-
611
- - Dashboard: https://cloud.saleor.io
612
- - Documentation: https://docs.saleor.io
613
- - API Reference: https://docs.saleor.io/api
614
-
615
- ## Saleor Skills
616
-
617
- This project includes Saleor agent skills:
618
- - saleor-app: App development patterns
619
- - saleor-configurator: Config as code
620
- - saleor-core: Backend internals
621
- - saleor-storefront: Storefront patterns
622
-
623
- ## MCP Server
624
-
625
- Configure saleor-mcp for AI agent capabilities:
626
- \`\`\`json
627
- {
628
- "mcpServers": {
629
- "saleor": {
630
- "url": "https://mcp.saleor.app"
631
- }
632
- }
633
- }
634
- \`\`\`
635
- `;
636
- const agentsMdPath = join2(projectPath, "AGENTS.md");
637
- writeFileSync2(agentsMdPath, agentsMdContent);
638
- info(` Created AGENTS.md`);
639
- }
640
- function createMcpConfig(projectPath) {
641
- const mcpConfig = {
642
- mcpServers: {
643
- saleor: {
644
- url: "https://mcp.saleor.app"
645
- }
646
- }
647
- };
648
- const mcpPath = join2(projectPath, ".mcp.json");
649
- writeFileSync2(mcpPath, JSON.stringify(mcpConfig, null, 2));
650
- info(` Created .mcp.json`);
651
- }
652
-
653
- // src/cli/commands/agent.ts
654
- var agentCommands = {
655
- command: "agent <action>",
656
- describe: "Configure AI agents for Saleor",
657
- builder: (yargs) => yargs.command({
658
- command: "setup",
659
- describe: "Setup AI agent with Saleor skills and MCP",
660
- builder: (yargs2) => yargs2.option("path", {
661
- alias: "p",
662
- type: "string",
663
- description: "Project path",
664
- default: "."
665
- }),
666
- handler: async (argv) => {
667
- await setupAgent(argv.path);
668
- }
669
- }).command({
670
- command: "skills",
671
- describe: "Install Saleor agent skills",
672
- builder: (yargs2) => yargs2.command({
673
- command: "install",
674
- describe: "Install Saleor skills",
675
- builder: (yargs3) => yargs3.option("path", {
676
- alias: "p",
677
- type: "string",
678
- description: "Project path",
679
- default: "."
680
- }),
681
- handler: async (argv) => {
682
- await installSkillsCommand(argv.path);
683
- }
684
- })
685
- })
686
- };
687
-
688
- // src/cli/commands/config.ts
689
- var configCommands = {
690
- command: "config <action>",
691
- describe: "Manage Saleor configuration",
692
- builder: (yargs) => yargs.command({
693
- command: "deploy",
694
- describe: "Deploy configuration to a store",
695
- builder: (yargs2) => yargs2.option("store", {
696
- alias: "s",
697
- type: "string",
698
- description: "Store ID",
699
- demandOption: true
700
- }),
701
- handler: async (argv) => {
702
- console.log(`Deploying config to store: ${argv.store}`);
703
- console.log("Config deployment not yet implemented");
704
- }
705
- }).command({
706
- command: "introspect",
707
- describe: "Introspect current store configuration",
708
- builder: (yargs2) => yargs2.option("store", {
709
- alias: "s",
710
- type: "string",
711
- description: "Store ID",
712
- demandOption: true
713
- }),
714
- handler: async (argv) => {
715
- console.log(`Introspecting store: ${argv.store}`);
716
- console.log("Config introspection not yet implemented");
717
- }
718
- })
719
- };
720
-
721
- // src/cli/index.ts
722
- yargs(hideBin(process.argv)).command(storeCommands).command(appCommands).command(agentCommands).command(configCommands).demandCommand(1, "You must provide a command").strict().parse();