@blocklet/pages-kit-block-studio 0.4.32 → 0.4.33
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/lib/cjs/components/create-resource.js +2 -2
- package/lib/cjs/constants/new-block-template/index.js +2 -14
- package/lib/cjs/middlewares/init-block-studio-router.js +15 -21
- package/lib/cjs/middlewares/init-resource-router.js +34 -42
- package/lib/cjs/plugins/vite-plugin-block-studio.js +107 -86
- package/lib/cjs/plugins/vite-plugin-html-transform.js +13 -24
- package/lib/cjs/plugins/vite-plugin-remote-script-localizer.js +87 -103
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/build-lib.js +62 -74
- package/lib/cjs/utils/generate-wrapper-code.js +366 -120
- package/lib/cjs/utils/helper.js +9 -19
- package/lib/esm/components/create-resource.js +2 -2
- package/lib/esm/constants/new-block-template/index.js +2 -14
- package/lib/esm/middlewares/init-block-studio-router.js +15 -21
- package/lib/esm/middlewares/init-resource-router.js +34 -42
- package/lib/esm/plugins/vite-plugin-block-studio.js +107 -86
- package/lib/esm/plugins/vite-plugin-html-transform.js +13 -24
- package/lib/esm/plugins/vite-plugin-remote-script-localizer.js +87 -103
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/build-lib.js +62 -74
- package/lib/esm/utils/generate-wrapper-code.js +366 -120
- package/lib/esm/utils/helper.js +9 -19
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -1,69 +1,61 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
|
-
export function generateWrapperCode(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
2
|
+
export async function generateWrapperCode({ project, state, version }) {
|
|
3
|
+
const projectName = (project.name || project.id).toLowerCase().replaceAll(/[^a-z0-9]/g, '-');
|
|
4
|
+
const packageName = `@pages-kit-project/${projectName}`;
|
|
5
|
+
const packageJson = JSON.stringify({
|
|
6
|
+
name: packageName,
|
|
7
|
+
version: version || '0.0.1',
|
|
8
|
+
main: 'index.cjs',
|
|
9
|
+
module: 'index.js',
|
|
10
|
+
types: 'index.d.ts',
|
|
11
|
+
peerDependencies: {
|
|
12
|
+
'@blocklet/pages-kit-runtime': 'latest',
|
|
13
|
+
'@blocklet/pages-kit-inner-components': 'latest',
|
|
14
|
+
'@blocklet/pages-kit': 'latest',
|
|
15
|
+
'@blocklet/uploader-server': 'latest',
|
|
16
|
+
'@arcblock/ux': 'latest',
|
|
17
|
+
'@mui/material': '5.16.14',
|
|
18
|
+
},
|
|
19
|
+
dependencies: {
|
|
20
|
+
'@blocklet/pages-kit-runtime': 'latest',
|
|
21
|
+
'@blocklet/pages-kit-inner-components': 'latest',
|
|
22
|
+
'@blocklet/pages-kit': 'latest',
|
|
23
|
+
'@blocklet/uploader-server': 'latest',
|
|
24
|
+
'@arcblock/ux': 'latest',
|
|
25
|
+
'@mui/material': '5.16.14',
|
|
26
|
+
},
|
|
27
|
+
exports: {
|
|
28
|
+
'.': {
|
|
29
|
+
require: './index.cjs',
|
|
30
|
+
import: './index.js',
|
|
31
|
+
types: './index.d.ts',
|
|
28
32
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
'@blocklet/uploader-server': 'latest',
|
|
34
|
-
'@arcblock/ux': 'latest',
|
|
35
|
-
'@mui/material': '5.16.14',
|
|
33
|
+
'./client': {
|
|
34
|
+
require: './client.cjs',
|
|
35
|
+
import: './client.js',
|
|
36
|
+
types: './client.d.ts',
|
|
36
37
|
},
|
|
37
|
-
|
|
38
|
-
'.'
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
types: './index.d.ts',
|
|
42
|
-
},
|
|
43
|
-
'./client': {
|
|
44
|
-
require: './client.cjs',
|
|
45
|
-
import: './client.js',
|
|
46
|
-
types: './client.d.ts',
|
|
47
|
-
},
|
|
48
|
-
'./middleware': {
|
|
49
|
-
require: './middleware.cjs',
|
|
50
|
-
import: './middleware.js',
|
|
51
|
-
types: './middleware.d.ts',
|
|
52
|
-
},
|
|
53
|
-
'./data.json': './data.json',
|
|
38
|
+
'./middleware': {
|
|
39
|
+
require: './middleware.cjs',
|
|
40
|
+
import: './middleware.js',
|
|
41
|
+
types: './middleware.d.ts',
|
|
54
42
|
},
|
|
55
|
-
|
|
56
|
-
|
|
43
|
+
'./data.json': './data.json',
|
|
44
|
+
},
|
|
45
|
+
}, null, 2);
|
|
46
|
+
const client = `\
|
|
57
47
|
import PageRenderComponent, { RuntimeProps, RuntimeType } from '@blocklet/pages-kit-runtime/client';
|
|
58
48
|
|
|
59
49
|
export type { RuntimeProps, RuntimeType };
|
|
60
50
|
|
|
61
51
|
${generatePageDataTypes(state)}
|
|
62
52
|
|
|
53
|
+
${generatePageDataJsonSchemas(state)}
|
|
54
|
+
|
|
63
55
|
export default PageRenderComponent;
|
|
64
56
|
`;
|
|
65
|
-
|
|
66
|
-
|
|
57
|
+
const index = client;
|
|
58
|
+
const middleware = `
|
|
67
59
|
import { Router } from 'express';
|
|
68
60
|
import axios from 'axios';
|
|
69
61
|
import { Component } from '@blocklet/sdk';
|
|
@@ -186,66 +178,71 @@ router.post('/api/components/preload', async (req, res) => {
|
|
|
186
178
|
|
|
187
179
|
export default router;
|
|
188
180
|
`;
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return [
|
|
209
|
-
{
|
|
210
|
-
fileName: 'data.json',
|
|
211
|
-
content: data,
|
|
212
|
-
},
|
|
213
|
-
];
|
|
214
|
-
}
|
|
215
|
-
const cjs = ts.transpileModule(content, {
|
|
216
|
-
fileName,
|
|
217
|
-
compilerOptions: Object.assign(Object.assign({}, compilerOptions), { module: ts.ModuleKind.CommonJS }),
|
|
218
|
-
});
|
|
219
|
-
const esm = ts.transpileModule(content, {
|
|
220
|
-
fileName,
|
|
221
|
-
compilerOptions: Object.assign(Object.assign({}, compilerOptions), { module: ts.ModuleKind.ESNext }),
|
|
222
|
-
});
|
|
223
|
-
// Generate proper type declarations
|
|
224
|
-
// const dts = ts.transpileModule(content, {
|
|
225
|
-
// fileName,
|
|
226
|
-
// compilerOptions: {
|
|
227
|
-
// ...compilerOptions,
|
|
228
|
-
// declaration: true,
|
|
229
|
-
// emitDeclarationOnly: true,
|
|
230
|
-
// },
|
|
231
|
-
// });
|
|
181
|
+
const data = JSON.stringify({
|
|
182
|
+
project,
|
|
183
|
+
state,
|
|
184
|
+
}, null, 2);
|
|
185
|
+
const tsFiles = [
|
|
186
|
+
{ fileName: 'index.ts', content: index },
|
|
187
|
+
{ fileName: 'client.ts', content: client },
|
|
188
|
+
{ fileName: 'middleware.ts', content: middleware },
|
|
189
|
+
{ fileName: 'data.json', content: data },
|
|
190
|
+
];
|
|
191
|
+
const ts = await import('typescript');
|
|
192
|
+
const compilerOptions = {
|
|
193
|
+
jsx: ts.JsxEmit.React,
|
|
194
|
+
esModuleInterop: true,
|
|
195
|
+
skipLibCheck: true,
|
|
196
|
+
declaration: true,
|
|
197
|
+
};
|
|
198
|
+
const result = (await Promise.all(tsFiles.map(async ({ fileName, content }) => {
|
|
199
|
+
if (fileName === 'data.json') {
|
|
232
200
|
return [
|
|
233
201
|
{
|
|
234
|
-
fileName:
|
|
235
|
-
content:
|
|
236
|
-
},
|
|
237
|
-
{
|
|
238
|
-
fileName: fileName.replace(/\.ts$/, '.js'),
|
|
239
|
-
content: esm.outputText,
|
|
240
|
-
},
|
|
241
|
-
{
|
|
242
|
-
fileName: fileName.replace(/\.ts$/, '.d.ts'),
|
|
243
|
-
content, // Fallback to original content if declaration fails
|
|
202
|
+
fileName: 'data.json',
|
|
203
|
+
content: data,
|
|
244
204
|
},
|
|
245
205
|
];
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
|
|
206
|
+
}
|
|
207
|
+
const cjs = ts.transpileModule(content, {
|
|
208
|
+
fileName,
|
|
209
|
+
compilerOptions: {
|
|
210
|
+
...compilerOptions,
|
|
211
|
+
module: ts.ModuleKind.CommonJS,
|
|
212
|
+
},
|
|
213
|
+
});
|
|
214
|
+
const esm = ts.transpileModule(content, {
|
|
215
|
+
fileName,
|
|
216
|
+
compilerOptions: {
|
|
217
|
+
...compilerOptions,
|
|
218
|
+
module: ts.ModuleKind.ESNext,
|
|
219
|
+
},
|
|
220
|
+
});
|
|
221
|
+
// Generate proper type declarations
|
|
222
|
+
// const dts = ts.transpileModule(content, {
|
|
223
|
+
// fileName,
|
|
224
|
+
// compilerOptions: {
|
|
225
|
+
// ...compilerOptions,
|
|
226
|
+
// declaration: true,
|
|
227
|
+
// emitDeclarationOnly: true,
|
|
228
|
+
// },
|
|
229
|
+
// });
|
|
230
|
+
return [
|
|
231
|
+
{
|
|
232
|
+
fileName: fileName.replace(/\.ts$/, '.cjs'),
|
|
233
|
+
content: cjs.outputText,
|
|
234
|
+
},
|
|
235
|
+
{
|
|
236
|
+
fileName: fileName.replace(/\.ts$/, '.js'),
|
|
237
|
+
content: esm.outputText,
|
|
238
|
+
},
|
|
239
|
+
{
|
|
240
|
+
fileName: fileName.replace(/\.ts$/, '.d.ts'),
|
|
241
|
+
content, // Fallback to original content if declaration fails
|
|
242
|
+
},
|
|
243
|
+
];
|
|
244
|
+
}))).flat();
|
|
245
|
+
return [...result, { fileName: 'package.json', content: packageJson }];
|
|
249
246
|
}
|
|
250
247
|
const basicComponentSectionTypes = {
|
|
251
248
|
iframe: `
|
|
@@ -289,6 +286,44 @@ function getCustomComponentPropertyType(type) {
|
|
|
289
286
|
}
|
|
290
287
|
const ALLOWED_PROPERTY_TYPES = ['string', 'multiline', 'url', 'json', 'yaml'];
|
|
291
288
|
function generatePageDataTypes(state) {
|
|
289
|
+
// 递归生成TypeScript类型属性
|
|
290
|
+
function generateTsTypeProperties(properties) {
|
|
291
|
+
return Object.entries(properties)
|
|
292
|
+
.map(([, prop]) => {
|
|
293
|
+
if (!prop.data)
|
|
294
|
+
return null;
|
|
295
|
+
// 如果key未定义,使用id
|
|
296
|
+
const key = prop.data.key || prop.data.id;
|
|
297
|
+
if (!key)
|
|
298
|
+
return null;
|
|
299
|
+
// 根据属性类型设置TypeScript类型
|
|
300
|
+
let typeStr = 'string';
|
|
301
|
+
if (prop.data.type === 'string' || prop.data.type === 'multiline') {
|
|
302
|
+
typeStr = 'string';
|
|
303
|
+
}
|
|
304
|
+
else if (prop.data.type === 'number') {
|
|
305
|
+
typeStr = 'number';
|
|
306
|
+
}
|
|
307
|
+
else if (prop.data.type === 'url') {
|
|
308
|
+
typeStr = '{ url: string; mediaKitUrl?: string; width?: number; height?: number }';
|
|
309
|
+
}
|
|
310
|
+
else if (prop.data.type === 'json' || prop.data.type === 'yaml') {
|
|
311
|
+
// 处理json类型和嵌套subProperties
|
|
312
|
+
if (prop.data.subProperties && Object.keys(prop.data.subProperties).length > 0) {
|
|
313
|
+
const subProps = generateTsTypeProperties(prop.data.subProperties).filter(Boolean).join('\n ');
|
|
314
|
+
typeStr = `{\n ${subProps}\n }`;
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
typeStr = 'any';
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
typeStr = 'any';
|
|
322
|
+
}
|
|
323
|
+
return ` "${key}"?: ${typeStr};`;
|
|
324
|
+
})
|
|
325
|
+
.filter(Boolean);
|
|
326
|
+
}
|
|
292
327
|
const pageTypeDefinitions = Object.values(state.pages)
|
|
293
328
|
.map((page) => {
|
|
294
329
|
if (!page.isTemplate)
|
|
@@ -302,7 +337,6 @@ function generatePageDataTypes(state) {
|
|
|
302
337
|
// 收集所有 section 的配置信息
|
|
303
338
|
const sectionTypes = page.sectionIds
|
|
304
339
|
.map((sectionId) => {
|
|
305
|
-
var _a, _b, _c, _d;
|
|
306
340
|
const section = page.sections[sectionId];
|
|
307
341
|
if (!section)
|
|
308
342
|
return null;
|
|
@@ -310,24 +344,30 @@ function generatePageDataTypes(state) {
|
|
|
310
344
|
if (!section.isTemplateSection)
|
|
311
345
|
return null;
|
|
312
346
|
if (section.component === 'custom-component') {
|
|
313
|
-
const componentId =
|
|
347
|
+
const componentId = section.config?.componentId;
|
|
314
348
|
if (!componentId)
|
|
315
349
|
return null;
|
|
316
|
-
const component =
|
|
350
|
+
const component = state.components[componentId]?.data || state.resources.components?.[componentId]?.component;
|
|
317
351
|
if (!component)
|
|
318
352
|
return null;
|
|
319
353
|
// 为自定义组件生成属性类型
|
|
320
354
|
const properties = Object.entries(component.properties || {})
|
|
321
355
|
.map(([, prop]) => {
|
|
322
|
-
var _a, _b, _c, _d, _e;
|
|
323
356
|
// check if the property type is allowed
|
|
324
|
-
if (
|
|
357
|
+
if (prop.data?.type && !ALLOWED_PROPERTY_TYPES.includes(prop.data?.type))
|
|
325
358
|
return null;
|
|
326
359
|
// if key is undefined, use id
|
|
327
|
-
const key =
|
|
360
|
+
const key = prop.data?.key || prop.data?.id;
|
|
328
361
|
if (!key)
|
|
329
362
|
return null;
|
|
330
|
-
|
|
363
|
+
// 处理JSON类型属性,如果有subProperties则递归生成类型
|
|
364
|
+
if ((prop.data?.type === 'json' || prop.data?.type === 'yaml') &&
|
|
365
|
+
prop.data?.subProperties &&
|
|
366
|
+
Object.keys(prop.data.subProperties).length > 0) {
|
|
367
|
+
const subProps = generateTsTypeProperties(prop.data.subProperties).filter(Boolean).join('\n ');
|
|
368
|
+
return ` "${key}"?: {\n ${subProps}\n };`;
|
|
369
|
+
}
|
|
370
|
+
return ` "${key}"?: ${getCustomComponentPropertyType(prop.data?.type)};`;
|
|
331
371
|
})
|
|
332
372
|
.filter(Boolean)
|
|
333
373
|
.join('\n');
|
|
@@ -358,13 +398,13 @@ ${sectionTypes}
|
|
|
358
398
|
})
|
|
359
399
|
.filter(Boolean);
|
|
360
400
|
// Generate type definitions string
|
|
361
|
-
const typeDefinitions = pageTypeDefinitions.map((def) => `export ${def
|
|
401
|
+
const typeDefinitions = pageTypeDefinitions.map((def) => `export ${def?.typeDefinition}`).join('\n\n');
|
|
362
402
|
// Generate string literals for each type
|
|
363
403
|
const typeStrings = pageTypeDefinitions
|
|
364
|
-
.map((def) => `export const ${def
|
|
404
|
+
.map((def) => `export const ${def?.typeName}String = \`${def?.typeDefinition}\`;`)
|
|
365
405
|
.join('\n\n');
|
|
366
406
|
// Generate union type
|
|
367
|
-
const pageUnionTypes = pageTypeDefinitions.map((def) => def
|
|
407
|
+
const pageUnionTypes = pageTypeDefinitions.map((def) => def?.typeName).join(' | ');
|
|
368
408
|
return `
|
|
369
409
|
// Page data type definitions
|
|
370
410
|
${typeDefinitions}
|
|
@@ -375,4 +415,210 @@ ${typeStrings}
|
|
|
375
415
|
// Union type of all page data types
|
|
376
416
|
export type PageDataUnion = ${pageUnionTypes || 'never'};`;
|
|
377
417
|
}
|
|
418
|
+
// 为每个页面数据类型生成JSONSchema
|
|
419
|
+
function generatePageDataJsonSchemas(state) {
|
|
420
|
+
// 递归生成JSON Schema属性
|
|
421
|
+
function generateJsonSchemaProperties(properties) {
|
|
422
|
+
const schemaProperties = {};
|
|
423
|
+
Object.entries(properties).forEach(([, prop]) => {
|
|
424
|
+
if (!prop.data)
|
|
425
|
+
return;
|
|
426
|
+
// 如果key未定义,使用id
|
|
427
|
+
const key = prop.data.key || prop.data.id;
|
|
428
|
+
if (!key)
|
|
429
|
+
return;
|
|
430
|
+
// 根据属性类型设置Schema
|
|
431
|
+
if (prop.data.type === 'string' || prop.data.type === 'multiline') {
|
|
432
|
+
schemaProperties[key] = { type: 'string' };
|
|
433
|
+
}
|
|
434
|
+
else if (prop.data.type === 'number') {
|
|
435
|
+
schemaProperties[key] = { type: 'number' };
|
|
436
|
+
}
|
|
437
|
+
else if (prop.data.type === 'url') {
|
|
438
|
+
schemaProperties[key] = {
|
|
439
|
+
type: 'object',
|
|
440
|
+
properties: {
|
|
441
|
+
url: { type: 'string' },
|
|
442
|
+
mediaKitUrl: { type: 'string' },
|
|
443
|
+
width: { type: 'number' },
|
|
444
|
+
height: { type: 'number' },
|
|
445
|
+
},
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
else if (prop.data.type === 'json' || prop.data.type === 'yaml') {
|
|
449
|
+
// 处理json类型和嵌套subProperties
|
|
450
|
+
if (prop.data.subProperties && Object.keys(prop.data.subProperties).length > 0) {
|
|
451
|
+
schemaProperties[key] = {
|
|
452
|
+
type: 'object',
|
|
453
|
+
properties: generateJsonSchemaProperties(prop.data.subProperties),
|
|
454
|
+
};
|
|
455
|
+
}
|
|
456
|
+
else {
|
|
457
|
+
schemaProperties[key] = {};
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
schemaProperties[key] = { type: 'string' };
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
return schemaProperties;
|
|
465
|
+
}
|
|
466
|
+
const pageSchemaDefinitions = Object.values(state.pages)
|
|
467
|
+
.map((page) => {
|
|
468
|
+
if (!page.isTemplate)
|
|
469
|
+
return null;
|
|
470
|
+
const typeName = `Page${page.slug
|
|
471
|
+
.replace(/^\//, '')
|
|
472
|
+
.split('/')
|
|
473
|
+
.map((s) => s.charAt(0).toUpperCase() + s.slice(1))
|
|
474
|
+
.join('')
|
|
475
|
+
.replace(/[^a-zA-Z0-9]/g, '')}Data`;
|
|
476
|
+
// 收集所有 section 的配置信息
|
|
477
|
+
const sectionProperties = {};
|
|
478
|
+
page.sectionIds.forEach((sectionId) => {
|
|
479
|
+
const section = page.sections[sectionId];
|
|
480
|
+
if (!section || !section.isTemplateSection)
|
|
481
|
+
return;
|
|
482
|
+
const sectionName = section.name || section.id;
|
|
483
|
+
if (section.component === 'custom-component') {
|
|
484
|
+
const componentId = section.config?.componentId;
|
|
485
|
+
if (!componentId)
|
|
486
|
+
return;
|
|
487
|
+
const component = state.components[componentId]?.data || state.resources.components?.[componentId]?.component;
|
|
488
|
+
if (!component)
|
|
489
|
+
return;
|
|
490
|
+
// 为自定义组件生成属性Schema
|
|
491
|
+
const properties = {};
|
|
492
|
+
Object.entries(component.properties || {}).forEach(([, prop]) => {
|
|
493
|
+
// 检查属性类型是否允许
|
|
494
|
+
if (prop.data?.type && !ALLOWED_PROPERTY_TYPES.includes(prop.data?.type))
|
|
495
|
+
return;
|
|
496
|
+
// 如果key未定义,使用id
|
|
497
|
+
const key = prop.data?.key || prop.data?.id;
|
|
498
|
+
if (!key)
|
|
499
|
+
return;
|
|
500
|
+
// 设置属性的Schema类型
|
|
501
|
+
if (prop.data?.type === 'string' || prop.data?.type === 'multiline') {
|
|
502
|
+
properties[key] = { type: 'string' };
|
|
503
|
+
}
|
|
504
|
+
else if (prop.data?.type === 'url') {
|
|
505
|
+
properties[key] = {
|
|
506
|
+
type: 'object',
|
|
507
|
+
properties: {
|
|
508
|
+
url: { type: 'string' },
|
|
509
|
+
mediaKitUrl: { type: 'string' },
|
|
510
|
+
width: { type: 'number' },
|
|
511
|
+
height: { type: 'number' },
|
|
512
|
+
},
|
|
513
|
+
};
|
|
514
|
+
}
|
|
515
|
+
else if (prop.data?.type === 'json' || prop.data?.type === 'yaml') {
|
|
516
|
+
// 处理json类型的属性
|
|
517
|
+
if (prop.data?.subProperties && Object.keys(prop.data.subProperties).length > 0) {
|
|
518
|
+
properties[key] = {
|
|
519
|
+
type: 'object',
|
|
520
|
+
properties: generateJsonSchemaProperties(prop.data.subProperties),
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
else {
|
|
524
|
+
properties[key] = {};
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
else {
|
|
528
|
+
properties[key] = { type: 'string' };
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
if (Object.keys(properties).length > 0) {
|
|
532
|
+
sectionProperties[sectionName] = {
|
|
533
|
+
type: 'object',
|
|
534
|
+
properties,
|
|
535
|
+
description: section.templateDescription,
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
else if (basicComponentSectionTypes[section.component]) {
|
|
540
|
+
// 处理基本组件section类型
|
|
541
|
+
const schemaProperties = {};
|
|
542
|
+
// 将类型字符串转换为JSONSchema格式
|
|
543
|
+
if (section.component === 'iframe') {
|
|
544
|
+
schemaProperties.src = { type: 'string' };
|
|
545
|
+
schemaProperties.title = { type: 'string' };
|
|
546
|
+
schemaProperties.description = { type: 'string' };
|
|
547
|
+
}
|
|
548
|
+
else if (section.component === 'section') {
|
|
549
|
+
schemaProperties.title = { type: 'string' };
|
|
550
|
+
schemaProperties.description = { type: 'string' };
|
|
551
|
+
schemaProperties.image = { type: 'string' };
|
|
552
|
+
schemaProperties.imageMeta = {
|
|
553
|
+
type: 'object',
|
|
554
|
+
properties: {
|
|
555
|
+
naturalWidth: { type: 'number' },
|
|
556
|
+
naturalHeight: { type: 'number' },
|
|
557
|
+
filename: { type: 'string' },
|
|
558
|
+
},
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
else if (section.component === 'section-card-list') {
|
|
562
|
+
schemaProperties.title = { type: 'string' };
|
|
563
|
+
schemaProperties.description = { type: 'string' };
|
|
564
|
+
schemaProperties.list = {
|
|
565
|
+
type: 'array',
|
|
566
|
+
items: {
|
|
567
|
+
type: 'object',
|
|
568
|
+
properties: {
|
|
569
|
+
id: { type: 'string' },
|
|
570
|
+
title: { type: 'string' },
|
|
571
|
+
description: { type: 'string' },
|
|
572
|
+
image: { type: 'string' },
|
|
573
|
+
},
|
|
574
|
+
},
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
else if (section.component === 'toc') {
|
|
578
|
+
schemaProperties.title = { type: 'string' };
|
|
579
|
+
schemaProperties.description = { type: 'string' };
|
|
580
|
+
}
|
|
581
|
+
sectionProperties[sectionName] = {
|
|
582
|
+
type: 'object',
|
|
583
|
+
properties: schemaProperties,
|
|
584
|
+
description: section.templateDescription,
|
|
585
|
+
};
|
|
586
|
+
}
|
|
587
|
+
else {
|
|
588
|
+
// 其他类型的section
|
|
589
|
+
sectionProperties[sectionName] = {
|
|
590
|
+
type: 'object',
|
|
591
|
+
properties: {},
|
|
592
|
+
description: section.templateDescription,
|
|
593
|
+
};
|
|
594
|
+
}
|
|
595
|
+
});
|
|
596
|
+
// 创建页面的JSONSchema定义
|
|
597
|
+
const schema = {
|
|
598
|
+
type: 'object',
|
|
599
|
+
properties: {
|
|
600
|
+
title: { type: 'string' },
|
|
601
|
+
image: { type: 'string' },
|
|
602
|
+
description: { type: 'string' },
|
|
603
|
+
sectionsData: {
|
|
604
|
+
type: 'object',
|
|
605
|
+
properties: sectionProperties,
|
|
606
|
+
description: '包含页面的所有部分数据',
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
};
|
|
610
|
+
return {
|
|
611
|
+
typeName: `${typeName}Schema`,
|
|
612
|
+
schema,
|
|
613
|
+
};
|
|
614
|
+
})
|
|
615
|
+
.filter(Boolean);
|
|
616
|
+
// 生成Schema导出代码
|
|
617
|
+
const schemaExports = pageSchemaDefinitions
|
|
618
|
+
.map((def) => `export const ${def?.typeName} = ${JSON.stringify(def?.schema, null, 2)};`)
|
|
619
|
+
.join('\n\n');
|
|
620
|
+
return `
|
|
621
|
+
// JSONSchema definitions for page data types
|
|
622
|
+
${schemaExports}`;
|
|
623
|
+
}
|
|
378
624
|
export default generateWrapperCode;
|
package/lib/esm/utils/helper.js
CHANGED
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
1
|
import { call } from '@blocklet/sdk/lib/component';
|
|
11
2
|
import config from '@blocklet/sdk/lib/config';
|
|
12
3
|
import fs from 'fs';
|
|
@@ -49,7 +40,7 @@ export function findComponentFiles(options = {}) {
|
|
|
49
40
|
metadata,
|
|
50
41
|
};
|
|
51
42
|
})
|
|
52
|
-
.filter(({ blockName }) => !
|
|
43
|
+
.filter(({ blockName }) => !filter?.length || filter.includes(blockName || ''));
|
|
53
44
|
}
|
|
54
45
|
export function getBlockName(entry) {
|
|
55
46
|
// First try to match index.{ts,tsx,html} pattern
|
|
@@ -75,7 +66,7 @@ export const isDev = process.env.BLOCKLET_MODE === 'development';
|
|
|
75
66
|
export const isMetadataFile = (filePath) => {
|
|
76
67
|
return filePath.endsWith(METADATA_FILE_NAME);
|
|
77
68
|
};
|
|
78
|
-
export const downloadAsset =
|
|
69
|
+
export const downloadAsset = async ({ asset, savePath, componentDid, }) => {
|
|
79
70
|
if (!componentDid || !isDev || !asset || !savePath) {
|
|
80
71
|
throw new Error('Invalid params');
|
|
81
72
|
}
|
|
@@ -85,9 +76,9 @@ export const downloadAsset = (_a) => __awaiter(void 0, [_a], void 0, function* (
|
|
|
85
76
|
}
|
|
86
77
|
const fileName = basename(asset);
|
|
87
78
|
// Ensure target directory exists
|
|
88
|
-
|
|
79
|
+
await mkdir(path.dirname(savePath), { recursive: true });
|
|
89
80
|
// download asset from pages-kit's /uploads
|
|
90
|
-
const res =
|
|
81
|
+
const res = await call({
|
|
91
82
|
name: process.env.BLOCKLET_COMPONENT_DID,
|
|
92
83
|
path: joinURL('/uploads', fileName),
|
|
93
84
|
responseType: 'stream',
|
|
@@ -95,12 +86,12 @@ export const downloadAsset = (_a) => __awaiter(void 0, [_a], void 0, function* (
|
|
|
95
86
|
});
|
|
96
87
|
if (res.status >= 200 && res.status < 400) {
|
|
97
88
|
const file = fs.createWriteStream(savePath);
|
|
98
|
-
|
|
89
|
+
await pipeline(res.data, file);
|
|
99
90
|
}
|
|
100
91
|
else {
|
|
101
92
|
throw new Error(`download asset failed ${res.status}`);
|
|
102
93
|
}
|
|
103
|
-
}
|
|
94
|
+
};
|
|
104
95
|
export const getPreviewImageRelativePath = (name) => {
|
|
105
96
|
return path.join(PREVIEW_IMAGE_DIR, name);
|
|
106
97
|
};
|
|
@@ -122,7 +113,7 @@ export function initializeMetadata(tempFilePath) {
|
|
|
122
113
|
try {
|
|
123
114
|
metadata = JSON.parse(content);
|
|
124
115
|
}
|
|
125
|
-
catch
|
|
116
|
+
catch {
|
|
126
117
|
// If parsing fails, use empty object
|
|
127
118
|
}
|
|
128
119
|
}
|
|
@@ -155,7 +146,6 @@ export function getBlockStudioInfo() {
|
|
|
155
146
|
}
|
|
156
147
|
export const isPagesKitBlockStudio = process.env.BLOCKLET_COMPONENT_DID === PAGES_KIT_BLOCK_STUDIO_DID;
|
|
157
148
|
export const getBlockCode = (filePath) => {
|
|
158
|
-
var _a;
|
|
159
149
|
// Check path safety first
|
|
160
150
|
if (!isPathSafe(filePath)) {
|
|
161
151
|
throw new Error('Invalid file path: path traversal detected');
|
|
@@ -166,7 +156,7 @@ export const getBlockCode = (filePath) => {
|
|
|
166
156
|
if (!files.length) {
|
|
167
157
|
throw new Error(`No code file found for block: ${blockName}`);
|
|
168
158
|
}
|
|
169
|
-
const codeFile =
|
|
159
|
+
const codeFile = files[0]?.fullPath;
|
|
170
160
|
if (!codeFile) {
|
|
171
161
|
throw new Error(`No code file found for block: ${blockName}`);
|
|
172
162
|
}
|
|
@@ -176,7 +166,7 @@ export const safeParse = (text) => {
|
|
|
176
166
|
try {
|
|
177
167
|
return JSON.parse(text);
|
|
178
168
|
}
|
|
179
|
-
catch
|
|
169
|
+
catch {
|
|
180
170
|
return null;
|
|
181
171
|
}
|
|
182
172
|
};
|