@blocklet/pages-kit-block-studio 0.0.18 → 0.1.0

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 (28) hide show
  1. package/lib/cjs/constants/index.js +12 -1
  2. package/lib/cjs/constants/new-block-template/@metadata.json +59 -0
  3. package/lib/cjs/constants/new-block-template/index.js +55 -0
  4. package/lib/cjs/constants/new-block-template/index.tsx +89 -0
  5. package/lib/cjs/middlewares/init-block-studio-router.js +43 -9
  6. package/lib/cjs/middlewares/init-resource-router.js +5 -1
  7. package/lib/cjs/plugins/vite-plugin-block-studio.js +29 -31
  8. package/lib/cjs/plugins/vite-plugin-html-transform.js +40 -5
  9. package/lib/cjs/tsconfig.tsbuildinfo +1 -1
  10. package/lib/cjs/utils/generate-wrapper-code.js +21 -25
  11. package/lib/cjs/utils/helper.js +20 -12
  12. package/lib/esm/constants/index.js +8 -0
  13. package/lib/esm/constants/new-block-template/@metadata.json +59 -0
  14. package/lib/esm/constants/new-block-template/index.js +50 -0
  15. package/lib/esm/constants/new-block-template/index.tsx +89 -0
  16. package/lib/esm/middlewares/init-block-studio-router.js +44 -10
  17. package/lib/esm/middlewares/init-resource-router.js +5 -1
  18. package/lib/esm/plugins/vite-plugin-block-studio.js +29 -31
  19. package/lib/esm/plugins/vite-plugin-html-transform.js +40 -5
  20. package/lib/esm/tsconfig.tsbuildinfo +1 -1
  21. package/lib/esm/utils/generate-wrapper-code.js +21 -25
  22. package/lib/esm/utils/helper.js +10 -6
  23. package/lib/types/constants/index.d.ts +7 -0
  24. package/lib/types/constants/new-block-template/index.d.ts +13 -0
  25. package/lib/types/tsconfig.tsbuildinfo +1 -1
  26. package/lib/types/utils/helper.d.ts +2 -4
  27. package/package.json +17 -5
  28. package/tsconfig.json +3 -1
@@ -275,12 +275,10 @@ function getCustomComponentPropertyType(type) {
275
275
  }
276
276
  const ALLOWED_PROPERTY_TYPES = ['string', 'multiline', 'url', 'json', 'yaml'];
277
277
  function generatePageDataTypes(state) {
278
- const pageTypes = Object.values(state.pages)
278
+ const pageTypeDefinitions = Object.values(state.pages)
279
279
  .map((page) => {
280
- // check if the page is a template page
281
280
  if (!page.isTemplate)
282
281
  return null;
283
- // 将 slug 转换为有效的 TypeScript 类型名
284
282
  const typeName = `Page${page.slug
285
283
  .replace(/^\//, '')
286
284
  .split('/')
@@ -331,8 +329,7 @@ ${properties}
331
329
  })
332
330
  .filter(Boolean)
333
331
  .join('\n');
334
- return `
335
- export interface ${typeName} {
332
+ const typeDefinition = `interface ${typeName} {
336
333
  title?: string;
337
334
  image?: string;
338
335
  description?: string;
@@ -340,29 +337,28 @@ export interface ${typeName} {
340
337
  ${sectionTypes}
341
338
  };
342
339
  }`;
340
+ return {
341
+ typeName,
342
+ typeDefinition,
343
+ };
343
344
  })
344
- .filter(Boolean)
345
- .join('\n');
346
- // 生成 PageData 类型的联合类型
347
- const pageUnionTypes = Object.values(state.pages)
348
- .map((page) => {
349
- if (!page.isTemplate)
350
- return null;
351
- const typeName = `Page${page.slug
352
- .replace(/^\//, '')
353
- .split('/')
354
- .map((s) => s.charAt(0).toUpperCase() + s.slice(1))
355
- .join('')
356
- .replace(/[^a-zA-Z0-9]/g, '')}Data`;
357
- return typeName;
358
- })
359
- .filter(Boolean)
360
- .join(' | ');
345
+ .filter(Boolean);
346
+ // Generate type definitions string
347
+ const typeDefinitions = pageTypeDefinitions.map((def) => `export ${def === null || def === void 0 ? void 0 : def.typeDefinition}`).join('\n\n');
348
+ // Generate string literals for each type
349
+ const typeStrings = pageTypeDefinitions
350
+ .map((def) => `export const ${def === null || def === void 0 ? void 0 : def.typeName}String = \`${def === null || def === void 0 ? void 0 : def.typeDefinition}\`;`)
351
+ .join('\n\n');
352
+ // Generate union type
353
+ const pageUnionTypes = pageTypeDefinitions.map((def) => def === null || def === void 0 ? void 0 : def.typeName).join(' | ');
361
354
  return `
362
- // 页面数据类型定义
363
- ${pageTypes}
355
+ // Page data type definitions
356
+ ${typeDefinitions}
357
+
358
+ // String versions of type definitions
359
+ ${typeStrings}
364
360
 
365
- // 所有页面数据类型的联合类型
361
+ // Union type of all page data types
366
362
  export type PageDataUnion = ${pageUnionTypes || 'never'};`;
367
363
  }
368
364
  exports.default = generateWrapperCode;
@@ -32,6 +32,9 @@ var __importStar = (this && this.__importStar) || (function () {
32
32
  return result;
33
33
  };
34
34
  })();
35
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
36
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
37
+ };
35
38
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
36
39
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
37
40
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -45,7 +48,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
45
48
  return (mod && mod.__esModule) ? mod : { "default": mod };
46
49
  };
47
50
  Object.defineProperty(exports, "__esModule", { value: true });
48
- exports.getBlockCode = exports.isPagesKitBlockStudio = exports.getPreviewImageRelativePath = exports.downloadAsset = exports.isMetadataFile = exports.isDev = exports.isPathSafe = exports.NANOID_LENGTH = exports.PREVIEW_IMAGE_DIR = exports.METADATA_FILE_NAME = exports.libDir = exports.logger = void 0;
51
+ exports.safeParse = exports.getBlockCode = exports.isPagesKitBlockStudio = exports.getPreviewImageRelativePath = exports.downloadAsset = exports.isMetadataFile = exports.isDev = exports.isPathSafe = exports.logger = void 0;
49
52
  exports.setBlockEntryFilesPattern = setBlockEntryFilesPattern;
50
53
  exports.getBlockEntryFilesPattern = getBlockEntryFilesPattern;
51
54
  exports.findComponentFiles = findComponentFiles;
@@ -64,14 +67,10 @@ const promises_2 = require("stream/promises");
64
67
  const ufo_1 = require("ufo");
65
68
  const yaml = __importStar(require("yaml"));
66
69
  const constants_1 = require("../constants");
70
+ __exportStar(require("../constants"), exports);
67
71
  exports.logger = console;
68
- exports.libDir = 'lib';
69
- exports.METADATA_FILE_NAME = '@metadata.json';
70
- exports.PREVIEW_IMAGE_DIR = '@preview-images';
71
- exports.NANOID_LENGTH = 16;
72
- const DEFAULT_BLOCK_ENTRY_FILES_PATTERN = 'src/**/index.{ts,tsx,html}';
73
72
  if (!process.env.BLOCK_ENTRY_FILES_PATTERN) {
74
- process.env.BLOCK_ENTRY_FILES_PATTERN = DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
73
+ process.env.BLOCK_ENTRY_FILES_PATTERN = constants_1.DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
75
74
  }
76
75
  function normalizePattern(pattern) {
77
76
  return pattern.replace(/^[/\\]+/, ''); // Remove leading slashes
@@ -80,7 +79,7 @@ function setBlockEntryFilesPattern(pattern) {
80
79
  process.env.BLOCK_ENTRY_FILES_PATTERN = normalizePattern(pattern);
81
80
  }
82
81
  function getBlockEntryFilesPattern() {
83
- return process.env.BLOCK_ENTRY_FILES_PATTERN || DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
82
+ return process.env.BLOCK_ENTRY_FILES_PATTERN || constants_1.DEFAULT_BLOCK_ENTRY_FILES_PATTERN;
84
83
  }
85
84
  function findComponentFiles(options = {}) {
86
85
  const { cwd = process.cwd(), filter } = options;
@@ -124,7 +123,7 @@ const isPathSafe = (filePath) => {
124
123
  exports.isPathSafe = isPathSafe;
125
124
  exports.isDev = process.env.BLOCKLET_MODE === 'development';
126
125
  const isMetadataFile = (filePath) => {
127
- return filePath.endsWith(exports.METADATA_FILE_NAME);
126
+ return filePath.endsWith(constants_1.METADATA_FILE_NAME);
128
127
  };
129
128
  exports.isMetadataFile = isMetadataFile;
130
129
  const downloadAsset = (_a) => __awaiter(void 0, [_a], void 0, function* ({ asset, savePath, componentDid, }) {
@@ -155,7 +154,7 @@ const downloadAsset = (_a) => __awaiter(void 0, [_a], void 0, function* ({ asset
155
154
  });
156
155
  exports.downloadAsset = downloadAsset;
157
156
  const getPreviewImageRelativePath = (name) => {
158
- return path_1.default.join(exports.PREVIEW_IMAGE_DIR, name);
157
+ return path_1.default.join(constants_1.PREVIEW_IMAGE_DIR, name);
159
158
  };
160
159
  exports.getPreviewImageRelativePath = getPreviewImageRelativePath;
161
160
  function initializeMetadata(tempFilePath) {
@@ -164,7 +163,7 @@ function initializeMetadata(tempFilePath) {
164
163
  throw new Error('File path is required');
165
164
  }
166
165
  // file path is metadata file
167
- const filePath = (0, exports.isMetadataFile)(tempFilePath) ? tempFilePath : path_1.default.join((0, path_1.dirname)(tempFilePath), exports.METADATA_FILE_NAME);
166
+ const filePath = (0, exports.isMetadataFile)(tempFilePath) ? tempFilePath : path_1.default.join((0, path_1.dirname)(tempFilePath), constants_1.METADATA_FILE_NAME);
168
167
  if (!filePath) {
169
168
  throw new Error('File path is required');
170
169
  }
@@ -182,7 +181,7 @@ function initializeMetadata(tempFilePath) {
182
181
  }
183
182
  // Add id if not exists
184
183
  if (!metadata.id) {
185
- metadata.id = (0, nanoid_1.nanoid)(exports.NANOID_LENGTH);
184
+ metadata.id = (0, nanoid_1.nanoid)(constants_1.NANOID_LENGTH);
186
185
  }
187
186
  // Add createdAt if not exists
188
187
  if (!metadata.createdAt) {
@@ -227,3 +226,12 @@ const getBlockCode = (filePath) => {
227
226
  return fs_1.default.readFileSync(codeFile, 'utf8');
228
227
  };
229
228
  exports.getBlockCode = getBlockCode;
229
+ const safeParse = (text) => {
230
+ try {
231
+ return JSON.parse(text);
232
+ }
233
+ catch (_a) {
234
+ return null;
235
+ }
236
+ };
237
+ exports.safeParse = safeParse;
@@ -1,6 +1,14 @@
1
+ import path from 'path';
1
2
  export const PAGES_KIT_DID = 'z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o';
2
3
  export const PAGES_KIT_RESOURCE_TYPE = 'page';
3
4
  export const PAGES_KIT_BLOCK_STUDIO_DID = 'z2qa7rr3eUyVnWp2PCxEVARuUfLFh6cE5V2xV';
4
5
  export const PAGES_KIT_BLOCK_STUDIO_RESOURCE_TYPE = 'page';
5
6
  export const MEDIA_KIT_DID = 'z8ia1mAXo8ZE7ytGF36L5uBf9kD2kenhqFGp9';
6
7
  export const MEDIA_KIT_RESOURCE_TYPE = 'imgpack';
8
+ export const NEW_BLOCK_TEMPLATE_PATH = path.join(__dirname, 'new-block-template', 'index.tsx');
9
+ export const NEW_BLOCK_TEMPLATE_METADATA_PATH = path.join(__dirname, 'new-block-template', '@metadata.json');
10
+ export const libDir = 'lib';
11
+ export const METADATA_FILE_NAME = '@metadata.json';
12
+ export const PREVIEW_IMAGE_DIR = '@preview-images';
13
+ export const NANOID_LENGTH = 16;
14
+ export const DEFAULT_BLOCK_ENTRY_FILES_PATTERN = 'src/**/index.{ts,tsx,html}';
@@ -0,0 +1,59 @@
1
+ {
2
+ "properties": {
3
+ "gs1rn5jmxfvpxptx": {
4
+ "index": 0,
5
+ "data": {
6
+ "id": "gs1rn5jmxfvpxptx",
7
+ "key": "title",
8
+ "locales": {
9
+ "zh": {
10
+ "name": "Title"
11
+ }
12
+ }
13
+ }
14
+ },
15
+ "9ajrz12ik7esfk1z": {
16
+ "index": 1,
17
+ "data": {
18
+ "id": "9ajrz12ik7esfk1z",
19
+ "key": "description",
20
+ "locales": {
21
+ "zh": {
22
+ "name": "Description",
23
+ "defaultValue": "Welcome to Pages Kit Block Studio"
24
+ }
25
+ }
26
+ }
27
+ },
28
+ "3ckcfvf6b7zyskk8": {
29
+ "index": 2,
30
+ "data": {
31
+ "id": "3ckcfvf6b7zyskk8",
32
+ "key": "logo",
33
+ "type": "url",
34
+ "locales": {
35
+ "zh": {
36
+ "defaultValue": {
37
+ "url": "/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80",
38
+ "mediaKitUrl": "/.well-known/service/blocklet/logo?imageFilter=convert&f=png&h=80"
39
+ },
40
+ "name": "Logo"
41
+ }
42
+ }
43
+ }
44
+ },
45
+ "x3lqht8ikble1itx": {
46
+ "index": 3,
47
+ "data": {
48
+ "id": "x3lqht8ikble1itx",
49
+ "key": "copyright",
50
+ "locales": {
51
+ "zh": {
52
+ "defaultValue": "Powered by Pages Kit Block Studio"
53
+ }
54
+ },
55
+ "visible": false
56
+ }
57
+ }
58
+ }
59
+ }
@@ -0,0 +1,50 @@
1
+ var __rest = (this && this.__rest) || function (s, e) {
2
+ var t = {};
3
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
4
+ t[p] = s[p];
5
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
6
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
7
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
8
+ t[p[i]] = s[p[i]];
9
+ }
10
+ return t;
11
+ };
12
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
+ // default export
14
+ export default function HelloWorld({ title = 'Hello World', logo, description, copyright }) {
15
+ return (_jsxs("div", { style: {
16
+ display: 'flex',
17
+ flexDirection: 'column',
18
+ alignItems: 'center',
19
+ padding: '16px 0',
20
+ }, children: [title && _jsx("h1", { children: title }), logo && (_jsx("img", { src: typeof logo === 'object' ? logo.url : logo, alt: "logo", style: {
21
+ margin: '16px 0',
22
+ maxWidth: '200px',
23
+ } })), description && (_jsx("div", { style: {
24
+ color: '#666',
25
+ marginTop: '8px',
26
+ }, children: description })), copyright && (_jsx("div", { style: {
27
+ color: '#999',
28
+ fontSize: '12px',
29
+ marginTop: '16px',
30
+ }, children: copyright }))] }));
31
+ }
32
+ // export edit component
33
+ export const EditComponent = (_a) => {
34
+ var { onChange } = _a, props = __rest(_a, ["onChange"]);
35
+ return (_jsxs("div", { style: { display: 'flex', flexDirection: 'column', gap: '16px' }, children: [_jsx("div", { style: {
36
+ fontSize: '14px',
37
+ fontWeight: 500,
38
+ color: '#333',
39
+ padding: '8px 0',
40
+ borderBottom: '1px solid #eee',
41
+ }, children: "Footer Parameters" }), _jsx("input", { id: "copyright-input", type: "text", style: {
42
+ width: '100%',
43
+ padding: '8px 12px',
44
+ border: '1px solid #ddd',
45
+ borderRadius: '4px',
46
+ fontSize: '14px',
47
+ transition: 'border-color 0.3s',
48
+ outline: 'none',
49
+ }, value: props.copyright || '', onChange: (e) => onChange === null || onChange === void 0 ? void 0 : onChange({ copyright: e.target.value }), placeholder: "Please Input Copyright" })] }));
50
+ };
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+
3
+ export interface HelloWorldProps {
4
+ title?: string;
5
+ logo?: string | { url: string };
6
+ description?: string;
7
+ copyright?: string;
8
+ }
9
+
10
+ // default export
11
+ export default function HelloWorld({ title = 'Hello World', logo, description, copyright }: HelloWorldProps) {
12
+ return (
13
+ <div
14
+ style={{
15
+ display: 'flex',
16
+ flexDirection: 'column',
17
+ alignItems: 'center',
18
+ padding: '16px 0',
19
+ }}>
20
+ {title && <h1>{title}</h1>}
21
+ {logo && (
22
+ <img
23
+ src={typeof logo === 'object' ? logo.url : logo}
24
+ alt="logo"
25
+ style={{
26
+ margin: '16px 0',
27
+ maxWidth: '200px',
28
+ }}
29
+ />
30
+ )}
31
+ {description && (
32
+ <div
33
+ style={{
34
+ color: '#666',
35
+ marginTop: '8px',
36
+ }}>
37
+ {description}
38
+ </div>
39
+ )}
40
+ {copyright && (
41
+ <div
42
+ style={{
43
+ color: '#999',
44
+ fontSize: '12px',
45
+ marginTop: '16px',
46
+ }}>
47
+ {copyright}
48
+ </div>
49
+ )}
50
+ </div>
51
+ );
52
+ }
53
+
54
+ // export edit component
55
+ export const EditComponent: React.FC<HelloWorldProps & { onChange?: (value: HelloWorldProps) => void }> = ({
56
+ onChange,
57
+ ...props
58
+ }) => {
59
+ return (
60
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
61
+ <div
62
+ style={{
63
+ fontSize: '14px',
64
+ fontWeight: 500,
65
+ color: '#333',
66
+ padding: '8px 0',
67
+ borderBottom: '1px solid #eee',
68
+ }}>
69
+ Footer Parameters
70
+ </div>
71
+ <input
72
+ id="copyright-input"
73
+ type="text"
74
+ style={{
75
+ width: '100%',
76
+ padding: '8px 12px',
77
+ border: '1px solid #ddd',
78
+ borderRadius: '4px',
79
+ fontSize: '14px',
80
+ transition: 'border-color 0.3s',
81
+ outline: 'none',
82
+ }}
83
+ value={props.copyright || ''}
84
+ onChange={(e) => onChange?.({ copyright: e.target.value })}
85
+ placeholder="Please Input Copyright"
86
+ />
87
+ </div>
88
+ );
89
+ };
@@ -11,7 +11,8 @@ import { Router } from 'express';
11
11
  import fs from 'fs';
12
12
  import { isEqual, keyBy, set } from 'lodash';
13
13
  import path from 'path';
14
- import { isPathSafe, isDev, downloadAsset, isMetadataFile, getPreviewImageRelativePath, initializeMetadata, findComponentFiles, getBlockStudioInfo, getBlockCode, } from '../utils/helper';
14
+ import { METADATA_FILE_NAME, NEW_BLOCK_TEMPLATE_PATH, NEW_BLOCK_TEMPLATE_METADATA_PATH } from '../constants';
15
+ import { isPathSafe, isDev, downloadAsset, isMetadataFile, getPreviewImageRelativePath, initializeMetadata, findComponentFiles, getBlockStudioInfo, getBlockCode, getBlockEntryFilesPattern, safeParse, } from '../utils/helper';
15
16
  export const initBlockStudioRouter = Router();
16
17
  const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.svg'];
17
18
  initBlockStudioRouter.get('/', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
@@ -37,11 +38,6 @@ initBlockStudioRouter.get('/', (req, res) => __awaiter(void 0, void 0, void 0, f
37
38
  return fs.createReadStream(filePath).pipe(res);
38
39
  }
39
40
  const metadata = initializeMetadata(filePath);
40
- const code = getBlockCode(filePath);
41
- if (code) {
42
- set(metadata, 'renderer.script', code);
43
- set(metadata, 'renderer.type', 'react-component');
44
- }
45
41
  return res.json(metadata);
46
42
  }
47
43
  catch (error) {
@@ -81,16 +77,54 @@ initBlockStudioRouter.post('/', (req, res) => __awaiter(void 0, void 0, void 0,
81
77
  });
82
78
  }
83
79
  }
84
- res.json({ success: true, content: mergedContent, message: 'Updated' });
85
- // save metadata without renderer after response
86
- delete mergedContent.renderer;
87
80
  fs.writeFileSync(filePath, JSON.stringify(mergedContent, null, 2));
88
- return null;
81
+ return res.json({ success: true, content: mergedContent, message: 'Updated' });
89
82
  }
90
83
  catch (error) {
91
84
  return res.status(500).json({ error: 'Failed to write file' });
92
85
  }
93
86
  }));
87
+ initBlockStudioRouter.post('/create', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
88
+ if (!isDev) {
89
+ return res.status(403).json({ error: 'Only available in development mode' });
90
+ }
91
+ const { name, description } = req.body;
92
+ if (!name) {
93
+ return res.status(400).json({ error: 'Name is required' });
94
+ }
95
+ try {
96
+ const pattern = getBlockEntryFilesPattern();
97
+ const baseDir = path.dirname(pattern.replace(/\*\*?/g, ''));
98
+ const blockDir = path.join(baseDir, name);
99
+ const metadataPath = path.join(blockDir, METADATA_FILE_NAME);
100
+ const indexPath = path.join(blockDir, 'index.tsx');
101
+ // Check if block already exists
102
+ if (fs.existsSync(blockDir)) {
103
+ return res.status(409).json({ error: 'Block already exists' });
104
+ }
105
+ // Create block directory
106
+ fs.mkdirSync(blockDir, { recursive: true });
107
+ // Initialize metadata
108
+ let metadata = initializeMetadata(metadataPath);
109
+ metadata.name = name;
110
+ metadata.description = description || '';
111
+ metadata.createdAt = new Date().toISOString();
112
+ metadata.updatedAt = new Date().toISOString();
113
+ // get template metadata from @metadata.json
114
+ const metadataContent = fs.readFileSync(NEW_BLOCK_TEMPLATE_METADATA_PATH, 'utf-8');
115
+ metadata = Object.assign(Object.assign({}, metadata), safeParse(metadataContent));
116
+ // Write metadata file
117
+ fs.writeFileSync(metadataPath, JSON.stringify(metadata, null, 2));
118
+ // Copy template file to index.tsx
119
+ const templateContent = fs.readFileSync(NEW_BLOCK_TEMPLATE_PATH, 'utf-8');
120
+ fs.writeFileSync(indexPath, templateContent);
121
+ return res.json({ success: true, metadata });
122
+ }
123
+ catch (error) {
124
+ console.error('Failed to create block:', error);
125
+ return res.status(500).json({ error: 'Failed to create block' });
126
+ }
127
+ }));
94
128
  initBlockStudioRouter.get('/all', (req, res) => __awaiter(void 0, void 0, void 0, function* () {
95
129
  const { withBlockletData = true } = req.query;
96
130
  const allBlocks = yield findComponentFiles();
@@ -98,7 +98,7 @@ initResourceRouter.post('/', (req, res) => __awaiter(void 0, void 0, void 0, fun
98
98
  const buildProcess = spawn('pnpm', ['run', 'build-lib'], {
99
99
  stdio: 'inherit',
100
100
  shell: true,
101
- env: Object.assign(Object.assign({}, process.env), { FORCE_COLOR: '1', BLOCK_FILTER: componentIds.join(',') }),
101
+ env: Object.assign(Object.assign({}, process.env), { FORCE_COLOR: '1', BLOCK_FILTER: componentIds.join(','), NODE_OPTIONS: '--max_old_space_size=16384' }),
102
102
  });
103
103
  yield new Promise((resolve, reject) => {
104
104
  buildProcess.on('close', (code) => {
@@ -107,6 +107,10 @@ initResourceRouter.post('/', (req, res) => __awaiter(void 0, void 0, void 0, fun
107
107
  else
108
108
  reject(new Error(`Build process exited with code ${code}`));
109
109
  });
110
+ buildProcess.on('error', (error) => {
111
+ console.error('Build process error:', error);
112
+ reject(error);
113
+ });
110
114
  });
111
115
  const dir = getExportDir(projectId, releaseId);
112
116
  fs.rmSync(dir, { recursive: true, force: true });
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  // import typescript from '@rollup/plugin-typescript';
12
12
  import { readFileSync, existsSync } from 'fs';
13
13
  import * as path from 'path';
14
+ import { joinURL } from 'ufo';
14
15
  import pages, { DefaultPageStrategy } from 'vite-plugin-react-pages';
15
16
  import { findComponentFiles, setBlockEntryFilesPattern, getBlockEntryFilesPattern, getBlockName, logger, } from '../utils/helper';
16
17
  import { initHtmlPreviewTransformPlugin, VIRTUAL_MODULE_ID, readHtmlFiles, generateComponent, } from './vite-plugin-html-transform';
@@ -72,18 +73,13 @@ export function initBlockStudioPlugins(options) {
72
73
  formats: ['es', !multiMode ? 'umd' : 'cjs'],
73
74
  fileName: (format, entryName) => `${format}/${entryName}.js`,
74
75
  }, rollupOptions: {
75
- external: [
76
- 'react',
77
- 'react-router-dom',
78
- 'react-dom',
79
- 'react-is',
80
- 'react/jsx-runtime',
81
- 'crypto',
82
- // '@emotion/react',
83
- // '@emotion/styled',
84
- '@arcblock/ux',
85
- '@arcblock/did-connect',
86
- ],
76
+ external: (id) => {
77
+ const skip = ['react', 'crypto'];
78
+ if (skip.some((s) => id === s)) {
79
+ return true;
80
+ }
81
+ return false;
82
+ },
87
83
  output: {
88
84
  chunkFileNames: () => {
89
85
  return '[format]/_chunks/[name]-[hash].js';
@@ -91,22 +87,13 @@ export function initBlockStudioPlugins(options) {
91
87
  // 为所有外部依赖提供全局变量
92
88
  globals: {
93
89
  react: 'React',
94
- 'react-dom': 'ReactDOM',
95
- 'react-is': 'ReactIs',
96
- 'react-router-dom': 'ReactRouterDOM',
97
- 'react/jsx-runtime': 'ReactJsxRuntime',
98
- // '@emotion/react': 'emotionReact',
99
- // '@emotion/styled': 'emotionStyled',
100
- '@mui/material': 'MUI',
101
- '@arcblock/ux': 'ArcBlockUX',
102
- '@arcblock/did-connect': 'ArcBlockDidConnect',
103
90
  },
104
91
  paths: {
105
- // Redirect 'react' imports to '@blocklet/pages-kit/builtin/react'
106
- // react: '@blocklet/pages-kit/builtin/react',
92
+ // Redirect 'react' imports to '@blocklet/pages-kit/builtin/react'
93
+ react: '@blocklet/pages-kit/builtin/react',
107
94
  },
108
95
  // 确保正确处理命名导出和默认导出
109
- // interop: 'auto',
96
+ interop: 'auto',
110
97
  },
111
98
  } }, _config === null || _config === void 0 ? void 0 : _config.build),
112
99
  };
@@ -126,21 +113,23 @@ export function initBlockStudioPlugins(options) {
126
113
  const pageId = `/${blockName}`;
127
114
  const dirPath = path.dirname(filePath);
128
115
  const metadataPath = path.join(dirPath, '@metadata.json');
116
+ const dataPath = isHtml ? `${VIRTUAL_MODULE_ID}?dir=${dirPath}` : filePath;
129
117
  api.addPageData({
130
118
  pageId,
131
- dataPath: isHtml ? `${VIRTUAL_MODULE_ID}?dir=${dirPath}` : filePath,
119
+ dataPath,
132
120
  staticData: isHtml
133
121
  ? {
134
- isHtmlPreview: true,
135
- dataPath: filePath,
136
- code: generateComponent(readHtmlFiles(dirPath.split('?dir=')[1] || '')),
122
+ isHtml: true,
123
+ dataPath,
124
+ code: generateComponent(readHtmlFiles(dirPath)),
137
125
  blockName,
138
126
  dirPath,
127
+ importPath: joinURL('@id', dataPath),
139
128
  metadataPath,
140
129
  }
141
- : Object.assign(Object.assign({}, (yield helpers.extractStaticData(file))), { code: readFileSync(file.path, 'utf-8'), dataPath: filePath, blockName,
142
- dirPath,
143
- metadataPath }),
130
+ : Object.assign(Object.assign({}, (yield helpers.extractStaticData(file))), { code: readFileSync(file.path, 'utf-8'), dataPath,
131
+ blockName,
132
+ dirPath, importPath: joinURL('@fs', dataPath), metadataPath }),
144
133
  });
145
134
  });
146
135
  });
@@ -161,6 +150,15 @@ export function initBlockStudioPlugins(options) {
161
150
  // maxConcurrent: 5, // 可选,默认值
162
151
  // timeout: 30 * 1000, // 可选,默认值 30 秒
163
152
  // }),
153
+ {
154
+ name: 'build-force-exit',
155
+ apply: 'build',
156
+ enforce: 'post',
157
+ closeBundle() {
158
+ // ensure vite build exit
159
+ process.exit(0);
160
+ },
161
+ },
164
162
  ];
165
163
  }
166
164
  export default initBlockStudioPlugins;