@oaysus/cli 0.1.13 → 0.1.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/README.md +35 -12
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +151 -85
- package/dist/cli.js.map +1 -1
- package/dist/components/App.d.ts +26 -10
- package/dist/components/App.d.ts.map +1 -1
- package/dist/components/App.js +23 -8
- package/dist/components/App.js.map +1 -1
- package/dist/components/SlashCommands.js +1 -1
- package/dist/lib/push.d.ts.map +1 -1
- package/dist/lib/push.js +29 -1
- package/dist/lib/push.js.map +1 -1
- package/dist/lib/shared/commands.d.ts +11 -1
- package/dist/lib/shared/commands.d.ts.map +1 -1
- package/dist/lib/shared/commands.js +55 -13
- package/dist/lib/shared/commands.js.map +1 -1
- package/dist/lib/shared/uploader.d.ts +1 -0
- package/dist/lib/shared/uploader.d.ts.map +1 -1
- package/dist/lib/shared/uploader.js +4 -2
- package/dist/lib/shared/uploader.js.map +1 -1
- package/dist/lib/site/asset-puller.d.ts +93 -0
- package/dist/lib/site/asset-puller.d.ts.map +1 -0
- package/dist/lib/site/asset-puller.js +376 -0
- package/dist/lib/site/asset-puller.js.map +1 -0
- package/dist/lib/site/asset-resolver.d.ts +44 -0
- package/dist/lib/site/asset-resolver.d.ts.map +1 -0
- package/dist/lib/site/asset-resolver.js +225 -0
- package/dist/lib/site/asset-resolver.js.map +1 -0
- package/dist/lib/site/asset-uploader.d.ts +58 -0
- package/dist/lib/site/asset-uploader.d.ts.map +1 -0
- package/dist/lib/site/asset-uploader.js +261 -0
- package/dist/lib/site/asset-uploader.js.map +1 -0
- package/dist/lib/site/index.d.ts +14 -0
- package/dist/lib/site/index.d.ts.map +1 -0
- package/dist/lib/site/index.js +15 -0
- package/dist/lib/site/index.js.map +1 -0
- package/dist/lib/site/metadata.d.ts +99 -0
- package/dist/lib/site/metadata.d.ts.map +1 -0
- package/dist/lib/site/metadata.js +470 -0
- package/dist/lib/site/metadata.js.map +1 -0
- package/dist/lib/site/page-publisher.d.ts +51 -0
- package/dist/lib/site/page-publisher.d.ts.map +1 -0
- package/dist/lib/site/page-publisher.js +460 -0
- package/dist/lib/site/page-publisher.js.map +1 -0
- package/dist/lib/site/page-puller.d.ts +93 -0
- package/dist/lib/site/page-puller.d.ts.map +1 -0
- package/dist/lib/site/page-puller.js +346 -0
- package/dist/lib/site/page-puller.js.map +1 -0
- package/dist/lib/site/page-validator.d.ts +29 -0
- package/dist/lib/site/page-validator.d.ts.map +1 -0
- package/dist/lib/site/page-validator.js +282 -0
- package/dist/lib/site/page-validator.js.map +1 -0
- package/dist/lib/site/project-loader.d.ts +45 -0
- package/dist/lib/site/project-loader.d.ts.map +1 -0
- package/dist/lib/site/project-loader.js +276 -0
- package/dist/lib/site/project-loader.js.map +1 -0
- package/dist/lib/site/shared-component-resolver.d.ts +89 -0
- package/dist/lib/site/shared-component-resolver.d.ts.map +1 -0
- package/dist/lib/site/shared-component-resolver.js +222 -0
- package/dist/lib/site/shared-component-resolver.js.map +1 -0
- package/dist/screens/WelcomeScreen.d.ts +26 -10
- package/dist/screens/WelcomeScreen.d.ts.map +1 -1
- package/dist/screens/WelcomeScreen.js +44 -21
- package/dist/screens/WelcomeScreen.js.map +1 -1
- package/dist/screens/site/SiteInitScreen.d.ts +12 -0
- package/dist/screens/site/SiteInitScreen.d.ts.map +1 -0
- package/dist/screens/site/SiteInitScreen.js +282 -0
- package/dist/screens/site/SiteInitScreen.js.map +1 -0
- package/dist/screens/site/SitePublishScreen.d.ts +15 -0
- package/dist/screens/site/SitePublishScreen.d.ts.map +1 -0
- package/dist/screens/site/SitePublishScreen.js +330 -0
- package/dist/screens/site/SitePublishScreen.js.map +1 -0
- package/dist/screens/site/SitePullScreen.d.ts +14 -0
- package/dist/screens/site/SitePullScreen.d.ts.map +1 -0
- package/dist/screens/site/SitePullScreen.js +455 -0
- package/dist/screens/site/SitePullScreen.js.map +1 -0
- package/dist/screens/site/SiteValidateScreen.d.ts +12 -0
- package/dist/screens/site/SiteValidateScreen.d.ts.map +1 -0
- package/dist/screens/site/SiteValidateScreen.js +201 -0
- package/dist/screens/site/SiteValidateScreen.js.map +1 -0
- package/dist/types/site.d.ts +348 -0
- package/dist/types/site.d.ts.map +1 -0
- package/dist/types/site.js +6 -0
- package/dist/types/site.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Puller
|
|
3
|
+
* Pulls pages from the Oaysus platform to local JSON files
|
|
4
|
+
*/
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
import * as fs from 'fs/promises';
|
|
7
|
+
import * as path from 'path';
|
|
8
|
+
import { loadCredentials } from '../shared/auth.js';
|
|
9
|
+
import { SSO_BASE_URL, debug } from '../shared/config.js';
|
|
10
|
+
/**
|
|
11
|
+
* Convert a slug to a local filename
|
|
12
|
+
* / -> home.json (matches site init convention)
|
|
13
|
+
* /about -> about.json
|
|
14
|
+
* /services/training -> services-training.json
|
|
15
|
+
*/
|
|
16
|
+
export function slugToFilename(slug) {
|
|
17
|
+
if (slug === '/') {
|
|
18
|
+
return 'home.json';
|
|
19
|
+
}
|
|
20
|
+
// Remove leading slash, replace remaining slashes with dashes
|
|
21
|
+
const name = slug.replace(/^\//, '').replace(/\//g, '-');
|
|
22
|
+
return `${name}.json`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Convert server page to local PageDefinition format
|
|
26
|
+
* Strips server-only fields but preserves shared component relationships
|
|
27
|
+
*/
|
|
28
|
+
function serverPageToLocal(serverPage) {
|
|
29
|
+
// Map components, preserving shared component info for round-trip
|
|
30
|
+
const localComponents = (serverPage.components || []).map(comp => {
|
|
31
|
+
const localComp = {
|
|
32
|
+
type: comp.type,
|
|
33
|
+
props: comp.props,
|
|
34
|
+
};
|
|
35
|
+
// Preserve optional fields
|
|
36
|
+
if (comp.id) {
|
|
37
|
+
localComp.id = comp.id;
|
|
38
|
+
}
|
|
39
|
+
if (comp.settings) {
|
|
40
|
+
localComp.settings = comp.settings;
|
|
41
|
+
}
|
|
42
|
+
// Preserve shared component info for round-trip support
|
|
43
|
+
if (comp.isGlobal && comp.globalId) {
|
|
44
|
+
localComp.shared = true;
|
|
45
|
+
localComp.globalId = comp.globalId;
|
|
46
|
+
}
|
|
47
|
+
return localComp;
|
|
48
|
+
});
|
|
49
|
+
return {
|
|
50
|
+
slug: serverPage.slug,
|
|
51
|
+
title: serverPage.title,
|
|
52
|
+
description: serverPage.description,
|
|
53
|
+
isHomePage: serverPage.isHomePage || false,
|
|
54
|
+
components: localComponents,
|
|
55
|
+
settings: serverPage.settings || {},
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Check if a file exists
|
|
60
|
+
*/
|
|
61
|
+
async function fileExists(filePath) {
|
|
62
|
+
try {
|
|
63
|
+
await fs.access(filePath);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Fetch all pages from the server
|
|
72
|
+
*/
|
|
73
|
+
async function fetchPages(websiteId, jwt) {
|
|
74
|
+
const url = `${SSO_BASE_URL}/hosting/page-builder/pages`;
|
|
75
|
+
debug('Fetching pages from:', url);
|
|
76
|
+
try {
|
|
77
|
+
const response = await axios.get(url, {
|
|
78
|
+
params: { websiteId },
|
|
79
|
+
headers: {
|
|
80
|
+
Authorization: `Bearer ${jwt}`,
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
if (response.data.success && response.data.pages) {
|
|
84
|
+
return { success: true, pages: response.data.pages };
|
|
85
|
+
}
|
|
86
|
+
return { success: false, pages: [], error: response.data.error || 'Unknown error' };
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
let errorMessage = 'Failed to fetch pages';
|
|
90
|
+
if (axios.isAxiosError(error)) {
|
|
91
|
+
if (error.response?.status === 401) {
|
|
92
|
+
errorMessage = 'Authentication failed. Please run "oaysus login"';
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
errorMessage = error.response?.data?.error ||
|
|
96
|
+
error.response?.data?.detail?.error ||
|
|
97
|
+
error.message;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else if (error instanceof Error) {
|
|
101
|
+
errorMessage = error.message;
|
|
102
|
+
}
|
|
103
|
+
return { success: false, pages: [], error: errorMessage };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Preview what pages would be pulled without actually pulling them
|
|
108
|
+
* Use this to show the user what will happen before confirming
|
|
109
|
+
*/
|
|
110
|
+
export async function previewPull(options) {
|
|
111
|
+
const { projectPath, config } = options;
|
|
112
|
+
// Get credentials if not provided
|
|
113
|
+
let websiteId = options.websiteId || config.websiteId;
|
|
114
|
+
let jwt = options.jwt;
|
|
115
|
+
if (!websiteId || !jwt) {
|
|
116
|
+
const credentials = await loadCredentials();
|
|
117
|
+
if (!credentials) {
|
|
118
|
+
return {
|
|
119
|
+
success: false,
|
|
120
|
+
error: 'Not logged in. Please run "oaysus login"',
|
|
121
|
+
pages: [],
|
|
122
|
+
newPages: [],
|
|
123
|
+
existingPages: [],
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
websiteId = websiteId || credentials.websiteId;
|
|
127
|
+
jwt = jwt || credentials.jwt;
|
|
128
|
+
}
|
|
129
|
+
if (!websiteId) {
|
|
130
|
+
return {
|
|
131
|
+
success: false,
|
|
132
|
+
error: 'No website ID found. Set websiteId in oaysus.website.json or run "oaysus login"',
|
|
133
|
+
pages: [],
|
|
134
|
+
newPages: [],
|
|
135
|
+
existingPages: [],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Fetch pages from server
|
|
139
|
+
const fetchResult = await fetchPages(websiteId, jwt);
|
|
140
|
+
if (!fetchResult.success) {
|
|
141
|
+
return {
|
|
142
|
+
success: false,
|
|
143
|
+
error: fetchResult.error || 'Failed to fetch pages',
|
|
144
|
+
pages: [],
|
|
145
|
+
newPages: [],
|
|
146
|
+
existingPages: [],
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
const serverPages = fetchResult.pages;
|
|
150
|
+
const pagesDir = path.join(projectPath, 'pages');
|
|
151
|
+
const pages = [];
|
|
152
|
+
const newPages = [];
|
|
153
|
+
const existingPages = [];
|
|
154
|
+
for (const serverPage of serverPages) {
|
|
155
|
+
const filename = slugToFilename(serverPage.slug);
|
|
156
|
+
const filePath = path.join(pagesDir, filename);
|
|
157
|
+
const relativePath = path.join('pages', filename);
|
|
158
|
+
const exists = await fileExists(filePath);
|
|
159
|
+
const previewPage = {
|
|
160
|
+
slug: serverPage.slug,
|
|
161
|
+
title: serverPage.title,
|
|
162
|
+
file: relativePath,
|
|
163
|
+
existsLocally: exists,
|
|
164
|
+
};
|
|
165
|
+
pages.push(previewPage);
|
|
166
|
+
if (exists) {
|
|
167
|
+
existingPages.push(previewPage);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
newPages.push(previewPage);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
return {
|
|
174
|
+
success: true,
|
|
175
|
+
pages,
|
|
176
|
+
newPages,
|
|
177
|
+
existingPages,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Pull all pages from the server to local files
|
|
182
|
+
*/
|
|
183
|
+
export async function pullPages(options) {
|
|
184
|
+
const { projectPath, config, force = false, dryRun = false, onProgress } = options;
|
|
185
|
+
// Get credentials if not provided
|
|
186
|
+
let websiteId = options.websiteId || config.websiteId;
|
|
187
|
+
let jwt = options.jwt;
|
|
188
|
+
if (!websiteId || !jwt) {
|
|
189
|
+
const credentials = await loadCredentials();
|
|
190
|
+
if (!credentials) {
|
|
191
|
+
return {
|
|
192
|
+
success: false,
|
|
193
|
+
pages: [],
|
|
194
|
+
fetched: 0,
|
|
195
|
+
written: 0,
|
|
196
|
+
skipped: 0,
|
|
197
|
+
errors: ['Not logged in. Please run "oaysus login"'],
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
websiteId = websiteId || credentials.websiteId;
|
|
201
|
+
jwt = jwt || credentials.jwt;
|
|
202
|
+
}
|
|
203
|
+
if (!websiteId) {
|
|
204
|
+
return {
|
|
205
|
+
success: false,
|
|
206
|
+
pages: [],
|
|
207
|
+
fetched: 0,
|
|
208
|
+
written: 0,
|
|
209
|
+
skipped: 0,
|
|
210
|
+
errors: ['No website ID found. Set websiteId in oaysus.website.json or run "oaysus login"'],
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
// Fetch pages from server
|
|
214
|
+
if (onProgress) {
|
|
215
|
+
onProgress('fetching', 0, 1);
|
|
216
|
+
}
|
|
217
|
+
const fetchResult = await fetchPages(websiteId, jwt);
|
|
218
|
+
if (!fetchResult.success) {
|
|
219
|
+
return {
|
|
220
|
+
success: false,
|
|
221
|
+
pages: [],
|
|
222
|
+
fetched: 0,
|
|
223
|
+
written: 0,
|
|
224
|
+
skipped: 0,
|
|
225
|
+
errors: [fetchResult.error || 'Failed to fetch pages'],
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
const serverPages = fetchResult.pages;
|
|
229
|
+
if (serverPages.length === 0) {
|
|
230
|
+
return {
|
|
231
|
+
success: true,
|
|
232
|
+
pages: [],
|
|
233
|
+
fetched: 0,
|
|
234
|
+
written: 0,
|
|
235
|
+
skipped: 0,
|
|
236
|
+
errors: [],
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (onProgress) {
|
|
240
|
+
onProgress('fetching', 1, 1);
|
|
241
|
+
}
|
|
242
|
+
// Ensure pages directory exists
|
|
243
|
+
const pagesDir = path.join(projectPath, 'pages');
|
|
244
|
+
if (!dryRun) {
|
|
245
|
+
await fs.mkdir(pagesDir, { recursive: true });
|
|
246
|
+
}
|
|
247
|
+
// Write pages to local files
|
|
248
|
+
const results = [];
|
|
249
|
+
let written = 0;
|
|
250
|
+
let skipped = 0;
|
|
251
|
+
const errors = [];
|
|
252
|
+
for (let i = 0; i < serverPages.length; i++) {
|
|
253
|
+
const serverPage = serverPages[i];
|
|
254
|
+
const filename = slugToFilename(serverPage.slug);
|
|
255
|
+
const filePath = path.join(pagesDir, filename);
|
|
256
|
+
const relativePath = path.join('pages', filename);
|
|
257
|
+
if (onProgress) {
|
|
258
|
+
onProgress('writing', i + 1, serverPages.length, serverPage.slug);
|
|
259
|
+
}
|
|
260
|
+
// Check if file already exists
|
|
261
|
+
const exists = await fileExists(filePath);
|
|
262
|
+
if (exists && !force) {
|
|
263
|
+
results.push({
|
|
264
|
+
slug: serverPage.slug,
|
|
265
|
+
file: relativePath,
|
|
266
|
+
action: 'skipped',
|
|
267
|
+
});
|
|
268
|
+
skipped++;
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
// Convert to local format
|
|
272
|
+
const localPage = serverPageToLocal(serverPage);
|
|
273
|
+
// Write file (unless dry run)
|
|
274
|
+
if (!dryRun) {
|
|
275
|
+
try {
|
|
276
|
+
const content = JSON.stringify(localPage, null, 2);
|
|
277
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
281
|
+
errors.push(`Failed to write ${filename}: ${errorMessage}`);
|
|
282
|
+
continue;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
results.push({
|
|
286
|
+
slug: serverPage.slug,
|
|
287
|
+
file: relativePath,
|
|
288
|
+
action: exists ? 'updated' : 'created',
|
|
289
|
+
});
|
|
290
|
+
written++;
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
success: errors.length === 0,
|
|
294
|
+
pages: results,
|
|
295
|
+
fetched: serverPages.length,
|
|
296
|
+
written,
|
|
297
|
+
skipped,
|
|
298
|
+
errors,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Format pull results for display
|
|
303
|
+
*/
|
|
304
|
+
export function formatPullResults(result) {
|
|
305
|
+
const lines = [];
|
|
306
|
+
if (result.fetched === 0) {
|
|
307
|
+
lines.push('No pages found on server');
|
|
308
|
+
return lines;
|
|
309
|
+
}
|
|
310
|
+
lines.push(`✓ Fetched ${result.fetched} page${result.fetched === 1 ? '' : 's'} from server`);
|
|
311
|
+
lines.push('');
|
|
312
|
+
if (result.written > 0 || result.skipped > 0) {
|
|
313
|
+
lines.push('Pages:');
|
|
314
|
+
for (const page of result.pages) {
|
|
315
|
+
const icon = page.action === 'created' ? '+' :
|
|
316
|
+
page.action === 'updated' ? '~' :
|
|
317
|
+
page.action === 'skipped' ? '-' : '?';
|
|
318
|
+
const suffix = page.action === 'skipped' ? ' (skipped, use --force to overwrite)' : '';
|
|
319
|
+
lines.push(` ${icon} ${page.file} (${page.slug})${suffix}`);
|
|
320
|
+
}
|
|
321
|
+
lines.push('');
|
|
322
|
+
}
|
|
323
|
+
if (result.errors.length > 0) {
|
|
324
|
+
lines.push('Errors:');
|
|
325
|
+
for (const error of result.errors) {
|
|
326
|
+
lines.push(` ✗ ${error}`);
|
|
327
|
+
}
|
|
328
|
+
lines.push('');
|
|
329
|
+
}
|
|
330
|
+
// Summary
|
|
331
|
+
const parts = [];
|
|
332
|
+
if (result.written > 0) {
|
|
333
|
+
parts.push(`${result.written} written`);
|
|
334
|
+
}
|
|
335
|
+
if (result.skipped > 0) {
|
|
336
|
+
parts.push(`${result.skipped} skipped`);
|
|
337
|
+
}
|
|
338
|
+
if (result.errors.length > 0) {
|
|
339
|
+
parts.push(`${result.errors.length} error${result.errors.length === 1 ? '' : 's'}`);
|
|
340
|
+
}
|
|
341
|
+
if (parts.length > 0) {
|
|
342
|
+
lines.push(`Summary: ${parts.join(', ')}`);
|
|
343
|
+
}
|
|
344
|
+
return lines;
|
|
345
|
+
}
|
|
346
|
+
//# sourceMappingURL=page-puller.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-puller.js","sourceRoot":"","sources":["../../../src/lib/site/page-puller.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Validator
|
|
3
|
+
* Validates pages against installed components on a website
|
|
4
|
+
*/
|
|
5
|
+
import type { PageDefinition, LoadedProject, PageValidationResult, SiteValidationResult, InstalledComponent } from '../../types/site.js';
|
|
6
|
+
/**
|
|
7
|
+
* Fetch installed components for a website
|
|
8
|
+
*/
|
|
9
|
+
export declare function fetchInstalledComponents(websiteId: string, jwt: string): Promise<InstalledComponent[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Validate a single page against installed components
|
|
12
|
+
*/
|
|
13
|
+
export declare function validatePage(pageFile: string, page: PageDefinition, installedComponents: InstalledComponent[], projectPath: string): Promise<PageValidationResult>;
|
|
14
|
+
/**
|
|
15
|
+
* Validate an entire website project
|
|
16
|
+
*/
|
|
17
|
+
export declare function validateProject(project: LoadedProject, options?: {
|
|
18
|
+
websiteId?: string;
|
|
19
|
+
jwt?: string;
|
|
20
|
+
}): Promise<SiteValidationResult>;
|
|
21
|
+
/**
|
|
22
|
+
* Get list of missing components across all pages
|
|
23
|
+
*/
|
|
24
|
+
export declare function getMissingComponents(result: SiteValidationResult): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Format validation results for display
|
|
27
|
+
*/
|
|
28
|
+
export declare function formatValidationResults(result: SiteValidationResult): string[];
|
|
29
|
+
//# sourceMappingURL=page-validator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-validator.d.ts","sourceRoot":"","sources":["../../../src/lib/site/page-validator.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,EAEnB,MAAM,qBAAqB,CAAC;AAM7B;;GAEG;AACH,wBAAsB,wBAAwB,CAC5C,SAAS,EAAE,MAAM,EACjB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAsC/B;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,cAAc,EACpB,mBAAmB,EAAE,kBAAkB,EAAE,EACzC,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,oBAAoB,CAAC,CA6D/B;AAED;;GAEG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE;IACP,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,CAAC,EAAE,MAAM,CAAC;CACT,GACL,OAAO,CAAC,oBAAoB,CAAC,CAqI/B;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,EAAE,CAQ3E;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,EAAE,CA6C9E"}
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Page Validator
|
|
3
|
+
* Validates pages against installed components on a website
|
|
4
|
+
*/
|
|
5
|
+
import axios from 'axios';
|
|
6
|
+
import { loadCredentials } from '../shared/auth.js';
|
|
7
|
+
import { SSO_BASE_URL, debug } from '../shared/config.js';
|
|
8
|
+
import { findAssetsInPage, assetExists } from './asset-resolver.js';
|
|
9
|
+
import { loadComponentCatalog, syncComponentCatalog, isCatalogStale } from './metadata.js';
|
|
10
|
+
/**
|
|
11
|
+
* Fetch installed components for a website
|
|
12
|
+
*/
|
|
13
|
+
export async function fetchInstalledComponents(websiteId, jwt) {
|
|
14
|
+
const url = `${SSO_BASE_URL}/hosting/page-builder/components/custom`;
|
|
15
|
+
debug('Fetching installed components');
|
|
16
|
+
debug('API URL:', url);
|
|
17
|
+
debug('Website ID:', websiteId);
|
|
18
|
+
try {
|
|
19
|
+
const response = await axios.get(url, {
|
|
20
|
+
params: { websiteId },
|
|
21
|
+
headers: {
|
|
22
|
+
Authorization: `Bearer ${jwt}`,
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
if (response.data.success && response.data.components) {
|
|
26
|
+
return response.data.components.map((c) => ({
|
|
27
|
+
id: c.id,
|
|
28
|
+
name: c.name,
|
|
29
|
+
displayName: c.displayName,
|
|
30
|
+
sourceThemePackId: c.themePackId,
|
|
31
|
+
sourceThemePackName: c.themePack?.displayName,
|
|
32
|
+
schema: c.schema,
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
if (axios.isAxiosError(error)) {
|
|
39
|
+
debug('Fetch components failed:', error.response?.status, error.response?.data);
|
|
40
|
+
throw new Error(error.response?.data?.error ||
|
|
41
|
+
error.response?.data?.detail?.error ||
|
|
42
|
+
'Failed to fetch installed components');
|
|
43
|
+
}
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Validate a single page against installed components
|
|
49
|
+
*/
|
|
50
|
+
export async function validatePage(pageFile, page, installedComponents, projectPath) {
|
|
51
|
+
const errors = [];
|
|
52
|
+
const warnings = [];
|
|
53
|
+
const unresolvedComponents = [];
|
|
54
|
+
const localAssets = [];
|
|
55
|
+
// Build lookup set for installed component names
|
|
56
|
+
const installedNames = new Set(installedComponents.map(c => c.name));
|
|
57
|
+
// Validate each component
|
|
58
|
+
for (let i = 0; i < page.components.length; i++) {
|
|
59
|
+
const component = page.components[i];
|
|
60
|
+
// Check if component type is installed
|
|
61
|
+
if (!installedNames.has(component.type)) {
|
|
62
|
+
unresolvedComponents.push(component.type);
|
|
63
|
+
errors.push(`Component "${component.type}" is not installed on this website`);
|
|
64
|
+
}
|
|
65
|
+
// TODO: Validate props against component schema
|
|
66
|
+
// This would require fetching and parsing the component schemas
|
|
67
|
+
}
|
|
68
|
+
// Find local asset references
|
|
69
|
+
const assets = findAssetsInPage(page, pageFile);
|
|
70
|
+
localAssets.push(...assets);
|
|
71
|
+
// Verify local assets exist
|
|
72
|
+
for (const asset of assets) {
|
|
73
|
+
const exists = await assetExists(asset, projectPath);
|
|
74
|
+
if (!exists) {
|
|
75
|
+
errors.push(`Asset not found: ${asset.localPath} (referenced in ${pageFile})`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Validate slug format
|
|
79
|
+
if (!page.slug.startsWith('/')) {
|
|
80
|
+
errors.push(`Slug must start with "/": ${page.slug}`);
|
|
81
|
+
}
|
|
82
|
+
// Warn about empty descriptions
|
|
83
|
+
if (!page.description) {
|
|
84
|
+
warnings.push('Page is missing a description (recommended for SEO)');
|
|
85
|
+
}
|
|
86
|
+
// Warn if SEO settings are missing
|
|
87
|
+
if (!page.settings?.seo?.metaTitle) {
|
|
88
|
+
warnings.push('Page is missing metaTitle in SEO settings');
|
|
89
|
+
}
|
|
90
|
+
return {
|
|
91
|
+
valid: errors.length === 0,
|
|
92
|
+
pageFile,
|
|
93
|
+
slug: page.slug,
|
|
94
|
+
errors,
|
|
95
|
+
warnings,
|
|
96
|
+
unresolvedComponents,
|
|
97
|
+
localAssets,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Validate an entire website project
|
|
102
|
+
*/
|
|
103
|
+
export async function validateProject(project, options = {}) {
|
|
104
|
+
// Get credentials if not provided
|
|
105
|
+
let websiteId = options.websiteId;
|
|
106
|
+
let jwt = options.jwt;
|
|
107
|
+
if (!websiteId || !jwt) {
|
|
108
|
+
const credentials = await loadCredentials();
|
|
109
|
+
if (!credentials) {
|
|
110
|
+
return {
|
|
111
|
+
valid: false,
|
|
112
|
+
pages: [],
|
|
113
|
+
totalErrors: 1,
|
|
114
|
+
totalWarnings: 0,
|
|
115
|
+
allAssets: [],
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
websiteId = websiteId || project.config.websiteId || credentials.websiteId;
|
|
119
|
+
jwt = jwt || credentials.jwt;
|
|
120
|
+
}
|
|
121
|
+
if (!websiteId) {
|
|
122
|
+
return {
|
|
123
|
+
valid: false,
|
|
124
|
+
pages: [{
|
|
125
|
+
valid: false,
|
|
126
|
+
pageFile: '',
|
|
127
|
+
slug: '',
|
|
128
|
+
errors: ['No website ID found. Set websiteId in oaysus.website.json or run "oaysus login"'],
|
|
129
|
+
warnings: [],
|
|
130
|
+
unresolvedComponents: [],
|
|
131
|
+
localAssets: [],
|
|
132
|
+
}],
|
|
133
|
+
totalErrors: 1,
|
|
134
|
+
totalWarnings: 0,
|
|
135
|
+
allAssets: [],
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
// Get installed components from local catalog or fetch from server
|
|
139
|
+
let installedComponents = [];
|
|
140
|
+
try {
|
|
141
|
+
// Check local catalog first
|
|
142
|
+
const catalog = await loadComponentCatalog(project.projectPath);
|
|
143
|
+
const isStale = await isCatalogStale(project.projectPath);
|
|
144
|
+
if (catalog && catalog.themePacks.length > 0 && !isStale) {
|
|
145
|
+
// Use local catalog
|
|
146
|
+
debug('Using local component catalog');
|
|
147
|
+
for (const pack of catalog.themePacks) {
|
|
148
|
+
for (const comp of pack.components) {
|
|
149
|
+
installedComponents.push({
|
|
150
|
+
id: `${pack.id}:${comp.type}`,
|
|
151
|
+
name: comp.type,
|
|
152
|
+
displayName: comp.displayName,
|
|
153
|
+
sourceThemePackId: pack.id,
|
|
154
|
+
sourceThemePackName: pack.name,
|
|
155
|
+
schema: comp.schema,
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
else {
|
|
161
|
+
// Sync catalog from server
|
|
162
|
+
debug('Syncing component catalog from server');
|
|
163
|
+
const syncResult = await syncComponentCatalog({
|
|
164
|
+
projectPath: project.projectPath,
|
|
165
|
+
websiteId,
|
|
166
|
+
jwt,
|
|
167
|
+
force: true,
|
|
168
|
+
});
|
|
169
|
+
if (syncResult.success && syncResult.catalog) {
|
|
170
|
+
for (const pack of syncResult.catalog.themePacks) {
|
|
171
|
+
for (const comp of pack.components) {
|
|
172
|
+
installedComponents.push({
|
|
173
|
+
id: `${pack.id}:${comp.type}`,
|
|
174
|
+
name: comp.type,
|
|
175
|
+
displayName: comp.displayName,
|
|
176
|
+
sourceThemePackId: pack.id,
|
|
177
|
+
sourceThemePackName: pack.name,
|
|
178
|
+
schema: comp.schema,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
// Fallback to direct API fetch if sync fails
|
|
185
|
+
installedComponents = await fetchInstalledComponents(websiteId, jwt);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (error) {
|
|
190
|
+
return {
|
|
191
|
+
valid: false,
|
|
192
|
+
pages: [{
|
|
193
|
+
valid: false,
|
|
194
|
+
pageFile: '',
|
|
195
|
+
slug: '',
|
|
196
|
+
errors: [`Failed to fetch installed components: ${error instanceof Error ? error.message : 'Unknown error'}`],
|
|
197
|
+
warnings: [],
|
|
198
|
+
unresolvedComponents: [],
|
|
199
|
+
localAssets: [],
|
|
200
|
+
}],
|
|
201
|
+
totalErrors: 1,
|
|
202
|
+
totalWarnings: 0,
|
|
203
|
+
allAssets: [],
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
// Validate each page
|
|
207
|
+
const pageResults = [];
|
|
208
|
+
const allAssets = [];
|
|
209
|
+
for (const page of project.pages) {
|
|
210
|
+
const result = await validatePage(page.file, page.definition, installedComponents, project.projectPath);
|
|
211
|
+
pageResults.push(result);
|
|
212
|
+
allAssets.push(...result.localAssets);
|
|
213
|
+
}
|
|
214
|
+
// Calculate totals
|
|
215
|
+
const totalErrors = pageResults.reduce((sum, p) => sum + p.errors.length, 0);
|
|
216
|
+
const totalWarnings = pageResults.reduce((sum, p) => sum + p.warnings.length, 0);
|
|
217
|
+
return {
|
|
218
|
+
valid: totalErrors === 0,
|
|
219
|
+
pages: pageResults,
|
|
220
|
+
totalErrors,
|
|
221
|
+
totalWarnings,
|
|
222
|
+
allAssets,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Get list of missing components across all pages
|
|
227
|
+
*/
|
|
228
|
+
export function getMissingComponents(result) {
|
|
229
|
+
const missing = new Set();
|
|
230
|
+
for (const page of result.pages) {
|
|
231
|
+
for (const comp of page.unresolvedComponents) {
|
|
232
|
+
missing.add(comp);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return Array.from(missing);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Format validation results for display
|
|
239
|
+
*/
|
|
240
|
+
export function formatValidationResults(result) {
|
|
241
|
+
const lines = [];
|
|
242
|
+
if (result.valid) {
|
|
243
|
+
lines.push('✓ All pages validated successfully');
|
|
244
|
+
lines.push(` ${result.pages.length} pages, ${result.allAssets.length} assets`);
|
|
245
|
+
}
|
|
246
|
+
else {
|
|
247
|
+
lines.push('✗ Validation failed');
|
|
248
|
+
lines.push('');
|
|
249
|
+
for (const page of result.pages) {
|
|
250
|
+
if (!page.valid) {
|
|
251
|
+
lines.push(` ${page.pageFile} (${page.slug})`);
|
|
252
|
+
for (const error of page.errors) {
|
|
253
|
+
lines.push(` ✗ ${error}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
// Show warnings even if valid
|
|
259
|
+
const pagesWithWarnings = result.pages.filter(p => p.warnings.length > 0);
|
|
260
|
+
if (pagesWithWarnings.length > 0) {
|
|
261
|
+
lines.push('');
|
|
262
|
+
lines.push('Warnings:');
|
|
263
|
+
for (const page of pagesWithWarnings) {
|
|
264
|
+
for (const warning of page.warnings) {
|
|
265
|
+
lines.push(` ⚠ ${page.pageFile}: ${warning}`);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
// Show missing components summary
|
|
270
|
+
const missing = getMissingComponents(result);
|
|
271
|
+
if (missing.length > 0) {
|
|
272
|
+
lines.push('');
|
|
273
|
+
lines.push('Missing components:');
|
|
274
|
+
for (const comp of missing) {
|
|
275
|
+
lines.push(` • ${comp}`);
|
|
276
|
+
}
|
|
277
|
+
lines.push('');
|
|
278
|
+
lines.push('Install these components via theme packs or upload them with "oaysus theme push"');
|
|
279
|
+
}
|
|
280
|
+
return lines;
|
|
281
|
+
}
|
|
282
|
+
//# sourceMappingURL=page-validator.js.map
|