@wix/web50-cli 0.1.0 → 0.1.2

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 (134) hide show
  1. package/bin/web5.js +1 -2
  2. package/dist/cjs/auth/deviceFlow.js +175 -16
  3. package/dist/cjs/auth/deviceFlow.js.map +1 -1
  4. package/dist/cjs/auth/index.js +93 -10
  5. package/dist/cjs/auth/index.js.map +1 -1
  6. package/dist/cjs/auth/secretStore.js.map +1 -1
  7. package/dist/cjs/cli.js +29 -1
  8. package/dist/cjs/cli.js.map +1 -1
  9. package/dist/cjs/commands/bundle.js +103 -0
  10. package/dist/cjs/commands/bundle.js.map +1 -0
  11. package/dist/cjs/commands/conversation.js +50 -0
  12. package/dist/cjs/commands/conversation.js.map +1 -0
  13. package/dist/cjs/commands/conversationWizard.js +528 -0
  14. package/dist/cjs/commands/conversationWizard.js.map +1 -0
  15. package/dist/cjs/commands/deploy.js +237 -0
  16. package/dist/cjs/commands/deploy.js.map +1 -0
  17. package/dist/cjs/commands/ecom.js +239 -0
  18. package/dist/cjs/commands/ecom.js.map +1 -0
  19. package/dist/cjs/commands/embed.js +118 -0
  20. package/dist/cjs/commands/embed.js.map +1 -0
  21. package/dist/cjs/commands/init.js +65 -29
  22. package/dist/cjs/commands/init.js.map +1 -1
  23. package/dist/cjs/commands/instructions.js +456 -0
  24. package/dist/cjs/commands/instructions.js.map +1 -0
  25. package/dist/cjs/commands/login.js +63 -4
  26. package/dist/cjs/commands/login.js.map +1 -1
  27. package/dist/cjs/commands/logout.js +16 -0
  28. package/dist/cjs/commands/logout.js.map +1 -0
  29. package/dist/cjs/commands/serve.js +122 -0
  30. package/dist/cjs/commands/serve.js.map +1 -0
  31. package/dist/cjs/commands/storybook.js +102 -0
  32. package/dist/cjs/commands/storybook.js.map +1 -0
  33. package/dist/cjs/commands/validate.js +617 -17
  34. package/dist/cjs/commands/validate.js.map +1 -1
  35. package/dist/cjs/commands/whoami.js +48 -0
  36. package/dist/cjs/commands/whoami.js.map +1 -0
  37. package/dist/cjs/templates/aiInstructionsSchema.js +5 -1
  38. package/dist/cjs/templates/aiInstructionsSchema.js.map +1 -1
  39. package/dist/cjs/templates/cmsMappingSchema.js +132 -0
  40. package/dist/cjs/templates/cmsMappingSchema.js.map +1 -0
  41. package/dist/cjs/utils/print.js +12 -0
  42. package/dist/cjs/utils/print.js.map +1 -1
  43. package/dist/cjs/utils/project.js +24 -0
  44. package/dist/cjs/utils/project.js.map +1 -1
  45. package/dist/cjs/utils/wixApi.js +57 -0
  46. package/dist/cjs/utils/wixApi.js.map +1 -0
  47. package/dist/esm/auth/deviceFlow.js +182 -17
  48. package/dist/esm/auth/deviceFlow.js.map +1 -1
  49. package/dist/esm/auth/index.js +98 -11
  50. package/dist/esm/auth/index.js.map +1 -1
  51. package/dist/esm/auth/secretStore.js.map +1 -1
  52. package/dist/esm/cli.js +29 -1
  53. package/dist/esm/cli.js.map +1 -1
  54. package/dist/esm/commands/bundle.js +100 -0
  55. package/dist/esm/commands/bundle.js.map +1 -0
  56. package/dist/esm/commands/conversation.js +44 -0
  57. package/dist/esm/commands/conversation.js.map +1 -0
  58. package/dist/esm/commands/conversationWizard.js +529 -0
  59. package/dist/esm/commands/conversationWizard.js.map +1 -0
  60. package/dist/esm/commands/deploy.js +239 -0
  61. package/dist/esm/commands/deploy.js.map +1 -0
  62. package/dist/esm/commands/ecom.js +234 -0
  63. package/dist/esm/commands/ecom.js.map +1 -0
  64. package/dist/esm/commands/embed.js +112 -0
  65. package/dist/esm/commands/embed.js.map +1 -0
  66. package/dist/esm/commands/init.js +66 -30
  67. package/dist/esm/commands/init.js.map +1 -1
  68. package/dist/esm/commands/instructions.js +459 -0
  69. package/dist/esm/commands/instructions.js.map +1 -0
  70. package/dist/esm/commands/login.js +66 -6
  71. package/dist/esm/commands/login.js.map +1 -1
  72. package/dist/esm/commands/logout.js +12 -0
  73. package/dist/esm/commands/logout.js.map +1 -0
  74. package/dist/esm/commands/serve.js +117 -0
  75. package/dist/esm/commands/serve.js.map +1 -0
  76. package/dist/esm/commands/storybook.js +97 -0
  77. package/dist/esm/commands/storybook.js.map +1 -0
  78. package/dist/esm/commands/validate.js +623 -19
  79. package/dist/esm/commands/validate.js.map +1 -1
  80. package/dist/esm/commands/whoami.js +44 -0
  81. package/dist/esm/commands/whoami.js.map +1 -0
  82. package/dist/esm/templates/aiInstructionsSchema.js +5 -1
  83. package/dist/esm/templates/aiInstructionsSchema.js.map +1 -1
  84. package/dist/esm/templates/cmsMappingSchema.js +128 -0
  85. package/dist/esm/templates/cmsMappingSchema.js.map +1 -0
  86. package/dist/esm/utils/print.js +10 -0
  87. package/dist/esm/utils/print.js.map +1 -1
  88. package/dist/esm/utils/project.js +23 -0
  89. package/dist/esm/utils/project.js.map +1 -1
  90. package/dist/esm/utils/wixApi.js +53 -0
  91. package/dist/esm/utils/wixApi.js.map +1 -0
  92. package/dist/types/auth/deviceFlow.d.ts +3 -1
  93. package/dist/types/auth/deviceFlow.d.ts.map +1 -1
  94. package/dist/types/auth/index.d.ts +6 -1
  95. package/dist/types/auth/index.d.ts.map +1 -1
  96. package/dist/types/auth/secretStore.d.ts +2 -0
  97. package/dist/types/auth/secretStore.d.ts.map +1 -1
  98. package/dist/types/commands/bundle.d.ts +10 -0
  99. package/dist/types/commands/bundle.d.ts.map +1 -0
  100. package/dist/types/commands/conversation.d.ts +3 -0
  101. package/dist/types/commands/conversation.d.ts.map +1 -0
  102. package/dist/types/commands/conversationWizard.d.ts +3 -0
  103. package/dist/types/commands/conversationWizard.d.ts.map +1 -0
  104. package/dist/types/commands/deploy.d.ts +3 -0
  105. package/dist/types/commands/deploy.d.ts.map +1 -0
  106. package/dist/types/commands/ecom.d.ts +3 -0
  107. package/dist/types/commands/ecom.d.ts.map +1 -0
  108. package/dist/types/commands/embed.d.ts +3 -0
  109. package/dist/types/commands/embed.d.ts.map +1 -0
  110. package/dist/types/commands/init.d.ts.map +1 -1
  111. package/dist/types/commands/instructions.d.ts +3 -0
  112. package/dist/types/commands/instructions.d.ts.map +1 -0
  113. package/dist/types/commands/login.d.ts.map +1 -1
  114. package/dist/types/commands/logout.d.ts +3 -0
  115. package/dist/types/commands/logout.d.ts.map +1 -0
  116. package/dist/types/commands/serve.d.ts +3 -0
  117. package/dist/types/commands/serve.d.ts.map +1 -0
  118. package/dist/types/commands/storybook.d.ts +3 -0
  119. package/dist/types/commands/storybook.d.ts.map +1 -0
  120. package/dist/types/commands/validate.d.ts +7 -0
  121. package/dist/types/commands/validate.d.ts.map +1 -1
  122. package/dist/types/commands/whoami.d.ts +3 -0
  123. package/dist/types/commands/whoami.d.ts.map +1 -0
  124. package/dist/types/templates/aiInstructionsSchema.d.ts.map +1 -1
  125. package/dist/types/templates/cmsMappingSchema.d.ts +2 -0
  126. package/dist/types/templates/cmsMappingSchema.d.ts.map +1 -0
  127. package/dist/types/utils/print.d.ts +3 -0
  128. package/dist/types/utils/print.d.ts.map +1 -1
  129. package/dist/types/utils/project.d.ts +12 -0
  130. package/dist/types/utils/project.d.ts.map +1 -1
  131. package/dist/types/utils/wixApi.d.ts +9 -0
  132. package/dist/types/utils/wixApi.d.ts.map +1 -0
  133. package/package.json +5 -5
  134. package/defaults/package.json +0 -42
@@ -0,0 +1,239 @@
1
+ import { Command } from 'commander';
2
+ import * as fs from 'fs';
3
+ import * as path from 'path';
4
+ import { load as yamlLoad } from 'js-yaml';
5
+ import { findProjectRoot } from '../utils/project';
6
+ import { wixRequest } from '../utils/wixApi';
7
+ import { success, error, warn, spinner, step } from '../utils/print';
8
+ import { execSync } from 'child_process';
9
+ import { runValidation } from './validate';
10
+ function getProjectRoot() {
11
+ const root = findProjectRoot(process.cwd());
12
+ if (!root) {
13
+ error('Not inside a web5 project. Run this command from your project directory.');
14
+ process.exit(1);
15
+ }
16
+ return root;
17
+ }
18
+
19
+ // ── Sub-deployers ─────────────────────────────────────────────────────────────
20
+
21
+ async function deployAiInstructions(root, opts) {
22
+ if (opts === void 0) {
23
+ opts = {};
24
+ }
25
+ const yamlPath = path.join(root, 'src', 'configuration', 'ai', 'prompt-instructions.yaml');
26
+ if (!fs.existsSync(yamlPath)) {
27
+ error(`AI instructions file not found: ${yamlPath}`);
28
+ process.exit(1);
29
+ }
30
+ const content = fs.readFileSync(yamlPath, 'utf8');
31
+ const parsed = yamlLoad(content);
32
+
33
+ // Load action definitions from src/actions/*.yaml
34
+ const actionsDir = path.join(root, 'src', 'actions');
35
+ const actionInstruction = [];
36
+ if (fs.existsSync(actionsDir)) {
37
+ const files = fs.readdirSync(actionsDir).filter(f => f.endsWith('.yaml'));
38
+ for (const file of files) {
39
+ const action = yamlLoad(fs.readFileSync(path.join(actionsDir, file), 'utf8'));
40
+ if (action) {
41
+ actionInstruction.push(action);
42
+ }
43
+ }
44
+ }
45
+ const body = {
46
+ intents: parsed.intent ?? {},
47
+ semantics: parsed.semantics ?? {},
48
+ actions: actionInstruction,
49
+ content: parsed.instructions ?? ''
50
+ };
51
+ const sp = spinner('Deploying AI instructions...');
52
+ try {
53
+ const data = await wixRequest({
54
+ path: '/web5/instruction/cli',
55
+ method: 'POST',
56
+ body
57
+ });
58
+ sp.stop();
59
+ success(`AI instructions deployed (version ${data.instruction.version})`);
60
+ if (opts.activate) {
61
+ const version = data.instruction.version;
62
+ const sp2 = spinner(`Activating version ${version}...`);
63
+ try {
64
+ await wixRequest({
65
+ path: `/web5/instructions/cli/activate/${version}`,
66
+ method: 'POST'
67
+ });
68
+ sp2.stop();
69
+ success(`Activated version ${version}`);
70
+ } catch (err_) {
71
+ sp2.stop();
72
+ error(err_.message);
73
+ process.exit(1);
74
+ }
75
+ }
76
+ } catch (err_) {
77
+ sp.stop();
78
+ error(err_.message);
79
+ process.exit(1);
80
+ }
81
+ }
82
+ async function deployComponents() {
83
+ warn('Components deploy: to be developed');
84
+ }
85
+
86
+ // ── Rollback ──────────────────────────────────────────────────────────────────
87
+
88
+ async function rollbackInstructions() {
89
+ const sp = spinner('Fetching instructions for rollback...');
90
+ try {
91
+ const data = await wixRequest({
92
+ path: '/web5/instructions/cli/query',
93
+ method: 'POST',
94
+ body: {
95
+ query: {}
96
+ }
97
+ });
98
+ sp.stop();
99
+ const instructions = data.instructions ?? [];
100
+ const active = instructions.find(i => i.active);
101
+ if (!active) {
102
+ error('No active instruction found — nothing to roll back from.');
103
+ process.exit(1);
104
+ }
105
+ const previous = instructions.filter(i => !i.active && i.version < active.version).sort((a, b) => b.version - a.version)[0];
106
+ if (!previous) {
107
+ error(`No previous version found before v${active.version}.`);
108
+ process.exit(1);
109
+ }
110
+ const sp2 = spinner(`Rolling back to version ${previous.version}...`);
111
+ await wixRequest({
112
+ path: `/web5/instructions/cli/activate/${previous.version}`,
113
+ method: 'POST'
114
+ });
115
+ sp2.stop();
116
+ success(`Rolled back to version ${previous.version} (was v${active.version})`);
117
+ } catch (err_) {
118
+ sp.stop();
119
+ error(err_.message);
120
+ process.exit(1);
121
+ }
122
+ }
123
+
124
+ // ── Helpers ───────────────────────────────────────────────────────────────────
125
+
126
+ function deriveValidationFilters(targets) {
127
+ const hasInstructions = targets.includes('instructions');
128
+ const hasComponents = targets.includes('components');
129
+ if (hasInstructions && hasComponents) {
130
+ return undefined; // validate everything
131
+ }
132
+ if (hasInstructions) {
133
+ return ['ai', 'actions'];
134
+ }
135
+ if (hasComponents) {
136
+ return ['cms', 'scripts', 'sections'];
137
+ }
138
+ return undefined;
139
+ }
140
+
141
+ // ── Stepped runner ────────────────────────────────────────────────────────────
142
+
143
+ async function runWithSteps(root, targets, opts) {
144
+ if (opts === void 0) {
145
+ opts = {};
146
+ }
147
+ const needsBundle = targets.includes('components');
148
+
149
+ // Calculate total steps
150
+ let totalSteps = 0;
151
+ if (!opts.skipValidate) {
152
+ totalSteps++;
153
+ }
154
+ if (needsBundle && !opts.skipBundle) {
155
+ totalSteps++;
156
+ }
157
+ totalSteps++; // deploy
158
+
159
+ let currentStep = 0;
160
+ if (!opts.skipValidate) {
161
+ step(++currentStep, totalSteps, 'Verification');
162
+ const filters = deriveValidationFilters(targets);
163
+ const valid = runValidation(root, filters);
164
+ if (!valid) {
165
+ error('Verification failed. Fix errors before deploying.');
166
+ process.exit(1);
167
+ }
168
+ }
169
+ if (needsBundle && !opts.skipBundle) {
170
+ step(++currentStep, totalSteps, 'Bundle');
171
+ try {
172
+ execSync('npm run bundle', {
173
+ cwd: root,
174
+ stdio: 'inherit'
175
+ });
176
+ } catch {
177
+ error('Bundle failed. Fix errors before deploying.');
178
+ process.exit(1);
179
+ }
180
+ }
181
+ step(++currentStep, totalSteps, 'Deploy');
182
+ for (const target of targets) {
183
+ if (target === 'components') {
184
+ await deployComponents();
185
+ }
186
+ if (target === 'instructions') {
187
+ await deployAiInstructions(root, {
188
+ activate: opts.activate
189
+ });
190
+ }
191
+ }
192
+ console.log('');
193
+ }
194
+
195
+ // ── Subcommands ───────────────────────────────────────────────────────────────
196
+
197
+ const instructionsCmd = new Command('instructions').description('Deploy AI instructions from src/configuration/ai/prompt-instructions.yaml').option('--skip-validate', 'Skip the pre-deploy validation step').option('--activate', 'Automatically activate the deployed version').action(async opts => {
198
+ const root = getProjectRoot();
199
+ await runWithSteps(root, ['instructions'], {
200
+ skipValidate: opts.skipValidate,
201
+ activate: opts.activate
202
+ });
203
+ });
204
+ const componentsCmd = new Command('components').description('Deploy components').option('--skip-validate', 'Skip the pre-deploy validation step').option('--skip-bundle', 'Skip the bundle step (reuse existing build artifact)').action(async opts => {
205
+ const root = getProjectRoot();
206
+ await runWithSteps(root, ['components'], {
207
+ skipValidate: opts.skipValidate,
208
+ skipBundle: opts.skipBundle
209
+ });
210
+ });
211
+
212
+ // ── Root deploy command ───────────────────────────────────────────────────────
213
+
214
+ export const deployCommand = new Command('deploy').description('Deploy project resources to the Web5 platform').option('--target <target>', 'What to deploy: instructions, components, or all').option('--skip-validate', 'Skip the pre-deploy validation step').option('--skip-bundle', 'Skip the bundle step (reuse existing build artifact)').option('--rollback', 'Re-activate the previous instruction version').action(async opts => {
215
+ const root = getProjectRoot();
216
+ if (opts.rollback) {
217
+ await rollbackInstructions();
218
+ return;
219
+ }
220
+ let targets;
221
+ if (!opts.target || opts.target === 'all') {
222
+ targets = ['components', 'instructions'];
223
+ } else if (opts.target === 'instructions' || opts.target === 'components') {
224
+ targets = [opts.target];
225
+ } else {
226
+ error(`Unknown target: '${opts.target}'. Valid values: instructions, components, all`);
227
+ process.exit(1);
228
+ }
229
+ await runWithSteps(root, targets, {
230
+ skipValidate: opts.skipValidate,
231
+ skipBundle: opts.skipBundle
232
+ });
233
+ }).addCommand(instructionsCmd).addCommand(componentsCmd);
234
+ deployCommand.on('command:*', _ref => {
235
+ let [cmd] = _ref;
236
+ error(`Unknown deploy target: '${cmd}'. Valid targets: components, instructions`);
237
+ process.exit(1);
238
+ });
239
+ //# sourceMappingURL=deploy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Command","fs","path","load","yamlLoad","findProjectRoot","wixRequest","success","error","warn","spinner","step","execSync","runValidation","getProjectRoot","root","process","cwd","exit","deployAiInstructions","opts","yamlPath","join","existsSync","content","readFileSync","parsed","actionsDir","actionInstruction","files","readdirSync","filter","f","endsWith","file","action","push","body","intents","intent","semantics","actions","instructions","sp","data","method","stop","instruction","version","activate","sp2","err_","message","deployComponents","rollbackInstructions","query","active","find","i","previous","sort","a","b","deriveValidationFilters","targets","hasInstructions","includes","hasComponents","undefined","runWithSteps","needsBundle","totalSteps","skipValidate","skipBundle","currentStep","filters","valid","stdio","target","console","log","instructionsCmd","description","option","componentsCmd","deployCommand","rollback","addCommand","on","_ref","cmd"],"sources":["../../../src/commands/deploy.ts"],"sourcesContent":["import { Command } from 'commander';\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { load as yamlLoad } from 'js-yaml';\nimport { findProjectRoot } from '../utils/project';\nimport { wixRequest } from '../utils/wixApi';\nimport { success, error, warn, spinner, step } from '../utils/print';\nimport { execSync } from 'child_process';\nimport { runValidation, DomainFilter } from './validate';\n\nfunction getProjectRoot(): string {\n const root = findProjectRoot(process.cwd());\n if (!root) {\n error(\n 'Not inside a web5 project. Run this command from your project directory.',\n );\n process.exit(1);\n }\n return root;\n}\n\n// ── Sub-deployers ─────────────────────────────────────────────────────────────\n\ninterface Instruction {\n id: string;\n version: number;\n content: string;\n active?: boolean;\n}\n\nasync function deployAiInstructions(\n root: string,\n opts: { activate?: boolean } = {},\n): Promise<void> {\n const yamlPath = path.join(\n root,\n 'src',\n 'configuration',\n 'ai',\n 'prompt-instructions.yaml',\n );\n\n if (!fs.existsSync(yamlPath)) {\n error(`AI instructions file not found: ${yamlPath}`);\n process.exit(1);\n }\n\n const content = fs.readFileSync(yamlPath, 'utf8');\n const parsed = yamlLoad(content) as {\n intent?: Record<string, string>;\n semantics?: Record<string, string>;\n instructions?: string;\n [key: string]: unknown;\n };\n\n // Load action definitions from src/actions/*.yaml\n const actionsDir = path.join(root, 'src', 'actions');\n const actionInstruction: unknown[] = [];\n if (fs.existsSync(actionsDir)) {\n const files = fs.readdirSync(actionsDir).filter((f) => f.endsWith('.yaml'));\n for (const file of files) {\n const action = yamlLoad(\n fs.readFileSync(path.join(actionsDir, file), 'utf8'),\n );\n if (action) {\n actionInstruction.push(action);\n }\n }\n }\n\n const body = {\n intents: parsed.intent ?? {},\n semantics: parsed.semantics ?? {},\n actions: actionInstruction,\n content: parsed.instructions ?? '',\n };\n\n const sp = spinner('Deploying AI instructions...');\n\n try {\n const data = await wixRequest<{ instruction: Instruction }>({\n path: '/web5/instruction/cli',\n method: 'POST',\n body,\n });\n sp.stop();\n success(`AI instructions deployed (version ${data.instruction.version})`);\n\n if (opts.activate) {\n const version = data.instruction.version;\n const sp2 = spinner(`Activating version ${version}...`);\n try {\n await wixRequest({\n path: `/web5/instructions/cli/activate/${version}`,\n method: 'POST',\n });\n sp2.stop();\n success(`Activated version ${version}`);\n } catch (err_) {\n sp2.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n }\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n}\n\nasync function deployComponents(): Promise<void> {\n warn('Components deploy: to be developed');\n}\n\n// ── Rollback ──────────────────────────────────────────────────────────────────\n\nasync function rollbackInstructions(): Promise<void> {\n const sp = spinner('Fetching instructions for rollback...');\n try {\n const data = await wixRequest<{ instructions: Instruction[] }>({\n path: '/web5/instructions/cli/query',\n method: 'POST',\n body: { query: {} },\n });\n sp.stop();\n\n const instructions = data.instructions ?? [];\n const active = instructions.find((i) => i.active);\n if (!active) {\n error('No active instruction found — nothing to roll back from.');\n process.exit(1);\n }\n\n const previous = instructions\n .filter((i) => !i.active && i.version < active.version)\n .sort((a, b) => b.version - a.version)[0];\n\n if (!previous) {\n error(`No previous version found before v${active.version}.`);\n process.exit(1);\n }\n\n const sp2 = spinner(`Rolling back to version ${previous.version}...`);\n await wixRequest({\n path: `/web5/instructions/cli/activate/${previous.version}`,\n method: 'POST',\n });\n sp2.stop();\n success(\n `Rolled back to version ${previous.version} (was v${active.version})`,\n );\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction deriveValidationFilters(\n targets: ('components' | 'instructions')[],\n): DomainFilter[] | undefined {\n const hasInstructions = targets.includes('instructions');\n const hasComponents = targets.includes('components');\n if (hasInstructions && hasComponents) {\n return undefined; // validate everything\n }\n if (hasInstructions) {\n return ['ai', 'actions'];\n }\n if (hasComponents) {\n return ['cms', 'scripts', 'sections'];\n }\n return undefined;\n}\n\n// ── Stepped runner ────────────────────────────────────────────────────────────\n\nasync function runWithSteps(\n root: string,\n targets: ('components' | 'instructions')[],\n opts: {\n skipValidate?: boolean;\n skipBundle?: boolean;\n activate?: boolean;\n } = {},\n): Promise<void> {\n const needsBundle = targets.includes('components');\n\n // Calculate total steps\n let totalSteps = 0;\n if (!opts.skipValidate) {\n totalSteps++;\n }\n if (needsBundle && !opts.skipBundle) {\n totalSteps++;\n }\n totalSteps++; // deploy\n\n let currentStep = 0;\n\n if (!opts.skipValidate) {\n step(++currentStep, totalSteps, 'Verification');\n const filters = deriveValidationFilters(targets);\n const valid = runValidation(root, filters);\n if (!valid) {\n error('Verification failed. Fix errors before deploying.');\n process.exit(1);\n }\n }\n\n if (needsBundle && !opts.skipBundle) {\n step(++currentStep, totalSteps, 'Bundle');\n try {\n execSync('npm run bundle', { cwd: root, stdio: 'inherit' });\n } catch {\n error('Bundle failed. Fix errors before deploying.');\n process.exit(1);\n }\n }\n\n step(++currentStep, totalSteps, 'Deploy');\n for (const target of targets) {\n if (target === 'components') {\n await deployComponents();\n }\n if (target === 'instructions') {\n await deployAiInstructions(root, { activate: opts.activate });\n }\n }\n\n console.log('');\n}\n\n// ── Subcommands ───────────────────────────────────────────────────────────────\n\nconst instructionsCmd = new Command('instructions')\n .description(\n 'Deploy AI instructions from src/configuration/ai/prompt-instructions.yaml',\n )\n .option('--skip-validate', 'Skip the pre-deploy validation step')\n .option('--activate', 'Automatically activate the deployed version')\n .action(async (opts: { skipValidate?: boolean; activate?: boolean }) => {\n const root = getProjectRoot();\n await runWithSteps(root, ['instructions'], {\n skipValidate: opts.skipValidate,\n activate: opts.activate,\n });\n });\n\nconst componentsCmd = new Command('components')\n .description('Deploy components')\n .option('--skip-validate', 'Skip the pre-deploy validation step')\n .option(\n '--skip-bundle',\n 'Skip the bundle step (reuse existing build artifact)',\n )\n .action(async (opts: { skipValidate?: boolean; skipBundle?: boolean }) => {\n const root = getProjectRoot();\n await runWithSteps(root, ['components'], {\n skipValidate: opts.skipValidate,\n skipBundle: opts.skipBundle,\n });\n });\n\n// ── Root deploy command ───────────────────────────────────────────────────────\n\nexport const deployCommand = new Command('deploy')\n .description('Deploy project resources to the Web5 platform')\n .option(\n '--target <target>',\n 'What to deploy: instructions, components, or all',\n )\n .option('--skip-validate', 'Skip the pre-deploy validation step')\n .option(\n '--skip-bundle',\n 'Skip the bundle step (reuse existing build artifact)',\n )\n .option('--rollback', 'Re-activate the previous instruction version')\n .action(\n async (opts: {\n target?: string;\n skipValidate?: boolean;\n skipBundle?: boolean;\n rollback?: boolean;\n }) => {\n const root = getProjectRoot();\n\n if (opts.rollback) {\n await rollbackInstructions();\n return;\n }\n\n type DeployTarget = 'components' | 'instructions';\n let targets: DeployTarget[];\n\n if (!opts.target || opts.target === 'all') {\n targets = ['components', 'instructions'];\n } else if (\n opts.target === 'instructions' ||\n opts.target === 'components'\n ) {\n targets = [opts.target as DeployTarget];\n } else {\n error(\n `Unknown target: '${opts.target}'. Valid values: instructions, components, all`,\n );\n process.exit(1);\n }\n\n await runWithSteps(root, targets, {\n skipValidate: opts.skipValidate,\n skipBundle: opts.skipBundle,\n });\n },\n )\n .addCommand(instructionsCmd)\n .addCommand(componentsCmd);\n\ndeployCommand.on('command:*', ([cmd]: string[]) => {\n error(\n `Unknown deploy target: '${cmd}'. Valid targets: components, instructions`,\n );\n process.exit(1);\n});\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,234 @@
1
+ import { Command } from 'commander';
2
+ import inquirer from 'inquirer';
3
+ import open from 'open';
4
+ import { wixRequest } from '../utils/wixApi';
5
+ import { success, error, info, spinner, isJsonMode } from '../utils/print';
6
+ const BASE = '/_api/ecom-integrations/v1/ecom-integrations';
7
+
8
+ // ── Types ─────────────────────────────────────────────────────────────────────
9
+
10
+ // ── connect ───────────────────────────────────────────────────────────────────
11
+
12
+ const POLL_INTERVAL_MS = 3000;
13
+ const POLL_TIMEOUT_MS = 120_000;
14
+ async function pollUntilActive() {
15
+ const deadline = Date.now() + POLL_TIMEOUT_MS;
16
+ while (Date.now() < deadline) {
17
+ await new Promise(r => setTimeout(r, POLL_INTERVAL_MS));
18
+ try {
19
+ const data = await wixRequest({
20
+ path: `${BASE}/connection-status`,
21
+ method: 'GET'
22
+ });
23
+ if (data.status === 'ACTIVE') {
24
+ return true;
25
+ }
26
+ } catch {
27
+ // ignore transient errors and keep polling
28
+ }
29
+ }
30
+ return false;
31
+ }
32
+ const connectCmd = new Command('connect').description('Connect a Shopify store via OAuth2 (opens browser)').option('--store-id <id>', 'Shopify store slug (e.g. mystore)').action(async opts => {
33
+ const statusSp = spinner('Checking connection status...');
34
+ try {
35
+ const statusData = await wixRequest({
36
+ path: `${BASE}/connection-status`,
37
+ method: 'GET'
38
+ });
39
+ statusSp.stop();
40
+ if (statusData.status === 'ACTIVE') {
41
+ error('Already connected. Use `web5 ecom disconnect` first to reconnect.');
42
+ process.exit(1);
43
+ }
44
+ } catch {
45
+ statusSp.stop();
46
+ // not connected yet, proceed
47
+ }
48
+ let storeId = opts.storeId;
49
+ if (!storeId) {
50
+ const answer = await inquirer.prompt([{
51
+ type: 'input',
52
+ name: 'storeId',
53
+ message: 'Shopify store slug (e.g. mystore):',
54
+ validate: v => v.trim().length > 0 || 'Store ID is required'
55
+ }]);
56
+ storeId = answer.storeId.trim();
57
+ }
58
+ const sp = spinner('Initiating Shopify OAuth...');
59
+ try {
60
+ const data = await wixRequest({
61
+ path: `${BASE}/shopify-oauth/initiate`,
62
+ method: 'POST',
63
+ body: {
64
+ platform: 'SHOPIFY',
65
+ shopify: {
66
+ storeId
67
+ }
68
+ }
69
+ });
70
+ sp.stop();
71
+ const url = data.authorizationUrl ?? data.authorization_url;
72
+ if (!url) {
73
+ error('No authorization URL returned by the server.');
74
+ process.exit(1);
75
+ }
76
+ info(`Authorization URL: ${url}`);
77
+ await open(url);
78
+ info('Browser opened — complete the Shopify authorization...');
79
+ const polling = spinner('Waiting for connection to become active...');
80
+ const active = await pollUntilActive();
81
+ polling.stop();
82
+ if (active) {
83
+ success('Connected! Your Shopify store is now active.');
84
+ } else {
85
+ error('Timed out waiting for the connection to become active. Run `web5 ecom status` to check.');
86
+ process.exit(1);
87
+ }
88
+ } catch (err_) {
89
+ sp.stop();
90
+ error(err_.message);
91
+ process.exit(1);
92
+ }
93
+ });
94
+
95
+ // ── status ────────────────────────────────────────────────────────────────────
96
+
97
+ const statusCmd = new Command('status').description('Show the current ecom provider connection status').action(async () => {
98
+ const sp = spinner('Fetching connection status...');
99
+ try {
100
+ const data = await wixRequest({
101
+ path: `${BASE}/connection-status`,
102
+ method: 'GET'
103
+ });
104
+ sp.stop();
105
+ if (isJsonMode()) {
106
+ console.log(JSON.stringify(data));
107
+ return;
108
+ }
109
+ const status = data.status ?? 'UNKNOWN';
110
+ if (status === 'UNKNOWN') {
111
+ info('Status: not connected');
112
+ return;
113
+ }
114
+ if (status === 'ACTIVE') {
115
+ success(`Status: ${status}`);
116
+ } else {
117
+ error(`Status: ${status}`);
118
+ if (data.errorMessage) {
119
+ info(`Error: ${data.errorMessage}`);
120
+ }
121
+ }
122
+ if (data.lastFullSync) {
123
+ info(`Last full sync: ${data.lastFullSync}`);
124
+ } else {
125
+ info('Last full sync: never');
126
+ }
127
+ if (data.lastAlignmentSync) {
128
+ info(`Last alignment: ${data.lastAlignmentSync}`);
129
+ } else {
130
+ info('Last alignment: never');
131
+ }
132
+ } catch (err_) {
133
+ sp.stop();
134
+ error(err_.message);
135
+ process.exit(1);
136
+ }
137
+ });
138
+
139
+ // ── full-sync ─────────────────────────────────────────────────────────────────
140
+
141
+ const fullSyncCmd = new Command('full-sync').description('Trigger a full sync from the ecom provider into CMS').action(async () => {
142
+ const sp = spinner('Running full sync...');
143
+ try {
144
+ const data = await wixRequest({
145
+ path: `${BASE}/full-sync`,
146
+ method: 'POST',
147
+ body: {}
148
+ });
149
+ sp.stop();
150
+ success(data.status ?? 'Full sync triggered');
151
+ } catch (err_) {
152
+ sp.stop();
153
+ error(err_.message);
154
+ process.exit(1);
155
+ }
156
+ });
157
+
158
+ // ── alignment-sync ────────────────────────────────────────────────────────────
159
+
160
+ const alignmentSyncCmd = new Command('alignment-sync').description('Run an alignment sync to catch any missed webhook updates').action(async () => {
161
+ const sp = spinner('Running alignment sync...');
162
+ try {
163
+ const data = await wixRequest({
164
+ path: `${BASE}/alignment-sync`,
165
+ method: 'POST',
166
+ body: {}
167
+ });
168
+ sp.stop();
169
+ success(data.status ?? 'Alignment sync complete');
170
+ const counts = data.syncedCounts ?? {};
171
+ for (const [table, count] of Object.entries(counts)) {
172
+ info(` ${table}: ${count}`);
173
+ }
174
+ } catch (err_) {
175
+ sp.stop();
176
+ error(err_.message);
177
+ process.exit(1);
178
+ }
179
+ });
180
+
181
+ // ── align-cms ─────────────────────────────────────────────────────────────────
182
+
183
+ const alignCmsCmd = new Command('align-cms').description('Align CMS collections with the ecom provider schema').action(async () => {
184
+ const sp = spinner('Aligning CMS collections...');
185
+ try {
186
+ await wixRequest({
187
+ path: `${BASE}/align-cms-collections`,
188
+ method: 'POST',
189
+ body: {}
190
+ });
191
+ sp.stop();
192
+ success('CMS collections aligned');
193
+ } catch (err_) {
194
+ sp.stop();
195
+ error(err_.message);
196
+ process.exit(1);
197
+ }
198
+ });
199
+
200
+ // ── disconnect ────────────────────────────────────────────────────────────────
201
+
202
+ const disconnectCmd = new Command('disconnect').description('Disconnect from the ecom provider').action(async () => {
203
+ const {
204
+ confirmed
205
+ } = await inquirer.prompt([{
206
+ type: 'confirm',
207
+ name: 'confirmed',
208
+ message: 'Are you sure you want to disconnect from the ecom provider?',
209
+ default: false
210
+ }]);
211
+ if (!confirmed) {
212
+ info('Disconnect cancelled.');
213
+ return;
214
+ }
215
+ const sp = spinner('Disconnecting...');
216
+ try {
217
+ await wixRequest({
218
+ path: `${BASE}/disconnect`,
219
+ method: 'POST',
220
+ body: {}
221
+ });
222
+ sp.stop();
223
+ success('Disconnected from ecom provider');
224
+ } catch (err_) {
225
+ sp.stop();
226
+ error(err_.message);
227
+ process.exit(1);
228
+ }
229
+ });
230
+
231
+ // ── root ecom command ─────────────────────────────────────────────────────────
232
+
233
+ export const ecomCommand = new Command('ecom').description('Manage ecom provider integrations').addCommand(connectCmd).addCommand(statusCmd).addCommand(fullSyncCmd).addCommand(alignmentSyncCmd).addCommand(alignCmsCmd).addCommand(disconnectCmd);
234
+ //# sourceMappingURL=ecom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["Command","inquirer","open","wixRequest","success","error","info","spinner","isJsonMode","BASE","POLL_INTERVAL_MS","POLL_TIMEOUT_MS","pollUntilActive","deadline","Date","now","Promise","r","setTimeout","data","path","method","status","connectCmd","description","option","action","opts","statusSp","statusData","stop","process","exit","storeId","answer","prompt","type","name","message","validate","v","trim","length","sp","body","platform","shopify","url","authorizationUrl","authorization_url","polling","active","err_","statusCmd","console","log","JSON","stringify","errorMessage","lastFullSync","lastAlignmentSync","fullSyncCmd","alignmentSyncCmd","counts","syncedCounts","table","count","Object","entries","alignCmsCmd","disconnectCmd","confirmed","default","ecomCommand","addCommand"],"sources":["../../../src/commands/ecom.ts"],"sourcesContent":["import { Command } from 'commander';\nimport inquirer from 'inquirer';\nimport open from 'open';\nimport { wixRequest } from '../utils/wixApi';\nimport { success, error, info, spinner, isJsonMode } from '../utils/print';\n\nconst BASE = '/_api/ecom-integrations/v1/ecom-integrations';\n\n// ── Types ─────────────────────────────────────────────────────────────────────\n\ninterface InitiateOAuthResponse {\n authorizationUrl?: string;\n authorization_url?: string;\n}\n\ninterface ConnectionStatusResponse {\n status?: string;\n platformMetadata?: Record<string, string>;\n lastFullSync?: string;\n lastAlignmentSync?: string;\n errorMessage?: string;\n}\n\ninterface SyncResponse {\n status?: string;\n syncedCounts?: Record<string, number>;\n}\n\n// ── connect ───────────────────────────────────────────────────────────────────\n\nconst POLL_INTERVAL_MS = 3000;\nconst POLL_TIMEOUT_MS = 120_000;\n\nasync function pollUntilActive(): Promise<boolean> {\n const deadline = Date.now() + POLL_TIMEOUT_MS;\n while (Date.now() < deadline) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));\n try {\n const data = await wixRequest<ConnectionStatusResponse>({\n path: `${BASE}/connection-status`,\n method: 'GET',\n });\n if (data.status === 'ACTIVE') {\n return true;\n }\n } catch {\n // ignore transient errors and keep polling\n }\n }\n return false;\n}\n\nconst connectCmd = new Command('connect')\n .description('Connect a Shopify store via OAuth2 (opens browser)')\n .option('--store-id <id>', 'Shopify store slug (e.g. mystore)')\n .action(async (opts: { storeId?: string }) => {\n const statusSp = spinner('Checking connection status...');\n try {\n const statusData = await wixRequest<ConnectionStatusResponse>({\n path: `${BASE}/connection-status`,\n method: 'GET',\n });\n statusSp.stop();\n if (statusData.status === 'ACTIVE') {\n error(\n 'Already connected. Use `web5 ecom disconnect` first to reconnect.',\n );\n process.exit(1);\n }\n } catch {\n statusSp.stop();\n // not connected yet, proceed\n }\n\n let storeId = opts.storeId;\n\n if (!storeId) {\n const answer = await inquirer.prompt<{ storeId: string }>([\n {\n type: 'input',\n name: 'storeId',\n message: 'Shopify store slug (e.g. mystore):',\n validate: (v: string) =>\n v.trim().length > 0 || 'Store ID is required',\n },\n ]);\n storeId = answer.storeId.trim();\n }\n\n const sp = spinner('Initiating Shopify OAuth...');\n try {\n const data = await wixRequest<InitiateOAuthResponse>({\n path: `${BASE}/shopify-oauth/initiate`,\n method: 'POST',\n body: {\n platform: 'SHOPIFY',\n shopify: { storeId },\n },\n });\n sp.stop();\n\n const url = data.authorizationUrl ?? data.authorization_url;\n if (!url) {\n error('No authorization URL returned by the server.');\n process.exit(1);\n }\n\n info(`Authorization URL: ${url}`);\n await open(url);\n info('Browser opened — complete the Shopify authorization...');\n\n const polling = spinner('Waiting for connection to become active...');\n const active = await pollUntilActive();\n polling.stop();\n\n if (active) {\n success('Connected! Your Shopify store is now active.');\n } else {\n error(\n 'Timed out waiting for the connection to become active. Run `web5 ecom status` to check.',\n );\n process.exit(1);\n }\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n });\n\n// ── status ────────────────────────────────────────────────────────────────────\n\nconst statusCmd = new Command('status')\n .description('Show the current ecom provider connection status')\n .action(async () => {\n const sp = spinner('Fetching connection status...');\n try {\n const data = await wixRequest<ConnectionStatusResponse>({\n path: `${BASE}/connection-status`,\n method: 'GET',\n });\n sp.stop();\n\n if (isJsonMode()) {\n console.log(JSON.stringify(data));\n return;\n }\n\n const status = data.status ?? 'UNKNOWN';\n\n if (status === 'UNKNOWN') {\n info('Status: not connected');\n return;\n }\n\n if (status === 'ACTIVE') {\n success(`Status: ${status}`);\n } else {\n error(`Status: ${status}`);\n if (data.errorMessage) {\n info(`Error: ${data.errorMessage}`);\n }\n }\n\n if (data.lastFullSync) {\n info(`Last full sync: ${data.lastFullSync}`);\n } else {\n info('Last full sync: never');\n }\n\n if (data.lastAlignmentSync) {\n info(`Last alignment: ${data.lastAlignmentSync}`);\n } else {\n info('Last alignment: never');\n }\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n });\n\n// ── full-sync ─────────────────────────────────────────────────────────────────\n\nconst fullSyncCmd = new Command('full-sync')\n .description('Trigger a full sync from the ecom provider into CMS')\n .action(async () => {\n const sp = spinner('Running full sync...');\n try {\n const data = await wixRequest<SyncResponse>({\n path: `${BASE}/full-sync`,\n method: 'POST',\n body: {},\n });\n sp.stop();\n success(data.status ?? 'Full sync triggered');\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n });\n\n// ── alignment-sync ────────────────────────────────────────────────────────────\n\nconst alignmentSyncCmd = new Command('alignment-sync')\n .description('Run an alignment sync to catch any missed webhook updates')\n .action(async () => {\n const sp = spinner('Running alignment sync...');\n try {\n const data = await wixRequest<SyncResponse>({\n path: `${BASE}/alignment-sync`,\n method: 'POST',\n body: {},\n });\n sp.stop();\n success(data.status ?? 'Alignment sync complete');\n\n const counts = data.syncedCounts ?? {};\n for (const [table, count] of Object.entries(counts)) {\n info(` ${table}: ${count}`);\n }\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n });\n\n// ── align-cms ─────────────────────────────────────────────────────────────────\n\nconst alignCmsCmd = new Command('align-cms')\n .description('Align CMS collections with the ecom provider schema')\n .action(async () => {\n const sp = spinner('Aligning CMS collections...');\n try {\n await wixRequest({\n path: `${BASE}/align-cms-collections`,\n method: 'POST',\n body: {},\n });\n sp.stop();\n success('CMS collections aligned');\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n });\n\n// ── disconnect ────────────────────────────────────────────────────────────────\n\nconst disconnectCmd = new Command('disconnect')\n .description('Disconnect from the ecom provider')\n .action(async () => {\n const { confirmed } = await inquirer.prompt<{ confirmed: boolean }>([\n {\n type: 'confirm',\n name: 'confirmed',\n message: 'Are you sure you want to disconnect from the ecom provider?',\n default: false,\n },\n ]);\n\n if (!confirmed) {\n info('Disconnect cancelled.');\n return;\n }\n\n const sp = spinner('Disconnecting...');\n try {\n await wixRequest({\n path: `${BASE}/disconnect`,\n method: 'POST',\n body: {},\n });\n sp.stop();\n success('Disconnected from ecom provider');\n } catch (err_) {\n sp.stop();\n error((err_ as Error).message);\n process.exit(1);\n }\n });\n\n// ── root ecom command ─────────────────────────────────────────────────────────\n\nexport const ecomCommand = new Command('ecom')\n .description('Manage ecom provider integrations')\n .addCommand(connectCmd)\n .addCommand(statusCmd)\n .addCommand(fullSyncCmd)\n .addCommand(alignmentSyncCmd)\n .addCommand(alignCmsCmd)\n .addCommand(disconnectCmd);\n"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,112 @@
1
+ import { Command } from 'commander';
2
+ import * as readline from 'readline';
3
+ import { execSync } from 'child_process';
4
+ import inquirer from 'inquirer';
5
+ import { wixRequest } from '../utils/wixApi';
6
+ import { isJsonMode } from '../utils/print';
7
+ import { findProjectRoot, readConfig, writeConfig } from '../utils/project';
8
+ function copyToClipboard(text) {
9
+ const cmd = process.platform === 'win32' ? `echo ${text} | clip` : process.platform === 'darwin' ? 'pbcopy' : 'xclip -selection clipboard';
10
+ execSync(process.platform === 'win32' ? `echo ${text} | clip` : cmd, process.platform === 'win32' ? undefined : {
11
+ input: text
12
+ });
13
+ }
14
+ async function promptCopyToClipboard(text) {
15
+ const rl = readline.createInterface({
16
+ input: process.stdin,
17
+ output: process.stdout
18
+ });
19
+ return new Promise(resolve => {
20
+ rl.question('\nPress Enter to copy to clipboard...', () => {
21
+ rl.close();
22
+ copyToClipboard(text);
23
+ console.log('Copied to clipboard.');
24
+ resolve();
25
+ });
26
+ });
27
+ }
28
+ async function promptForType() {
29
+ const {
30
+ type
31
+ } = await inquirer.prompt([{
32
+ type: 'list',
33
+ name: 'type',
34
+ message: 'Select embed type:',
35
+ choices: [{
36
+ name: 'Script tag',
37
+ value: 'script'
38
+ }, {
39
+ name: 'React component',
40
+ value: 'react'
41
+ }]
42
+ }]);
43
+ return type;
44
+ }
45
+ async function getOrCreateClientId() {
46
+ var _createData$oAuthApp;
47
+ console.log('Searching for client ID...');
48
+ const queryData = await wixRequest({
49
+ path: '/oauth-app/v1/oauth-apps/query',
50
+ method: 'POST',
51
+ body: {}
52
+ });
53
+ const apps = queryData.oAuthApps ?? [];
54
+ const existing = apps.find(app => app.name === 'web5');
55
+ if (existing) {
56
+ console.log(`Found client ID: ${existing.id}`);
57
+ return existing.id;
58
+ }
59
+ console.log('Client ID not found, creating...');
60
+ const createData = await wixRequest({
61
+ path: '/oauth-app/v1/oauth-apps',
62
+ method: 'POST',
63
+ body: {
64
+ oAuthApp: {
65
+ name: 'web5',
66
+ application_type: 'WEB_APP'
67
+ }
68
+ }
69
+ });
70
+ const id = (_createData$oAuthApp = createData.oAuthApp) == null ? void 0 : _createData$oAuthApp.id;
71
+ if (!id) {
72
+ throw new Error('Failed to create OAuth app — no ID returned');
73
+ }
74
+ console.log(`Client ID created: ${id}`);
75
+ return id;
76
+ }
77
+ export const embedCommand = new Command('embed').description('Generate embed code for a Web5 component').option('--type <type>', 'Embed type: script or react').option('--client-id <id>', 'Use this client ID instead of fetching from the API').option('--no-clipboard', 'Print to stdout only — skip the clipboard prompt').action(async opts => {
78
+ try {
79
+ const type = opts.type ?? (await promptForType());
80
+ if (type === 'react') {
81
+ console.log('no react for now');
82
+ return;
83
+ }
84
+ const root = findProjectRoot(process.cwd());
85
+ const config = root ? readConfig(root) : null;
86
+ const clientId = opts.clientId ?? ((config == null ? void 0 : config.clientId) || undefined) ?? (await getOrCreateClientId());
87
+ if (root && config && config.clientId !== clientId) {
88
+ writeConfig(root, {
89
+ ...config,
90
+ clientId
91
+ });
92
+ }
93
+ const embedScript = `<script src="https://www.wix.com/embed/v1/component.js" data-client-id="${clientId}"></script>`;
94
+ if (isJsonMode()) {
95
+ console.log(JSON.stringify({
96
+ type,
97
+ clientId,
98
+ embedCode: embedScript
99
+ }));
100
+ return;
101
+ }
102
+ console.log('\nEmbed script:\n');
103
+ console.log(embedScript);
104
+ if (opts.clipboard !== false && process.stdout.isTTY) {
105
+ await promptCopyToClipboard(embedScript);
106
+ }
107
+ } catch (err) {
108
+ console.error('Error:', err.message);
109
+ process.exit(1);
110
+ }
111
+ });
112
+ //# sourceMappingURL=embed.js.map