@blocklet/pages-kit-block-studio 0.4.66 → 0.4.68
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/middlewares/init-block-studio-router.js +14 -3
- package/lib/cjs/plugins/_theme.js +279 -241
- package/lib/cjs/tsconfig.tsbuildinfo +1 -1
- package/lib/cjs/utils/ts-morph-utils.js +63 -0
- package/lib/cjs/utils/zod-utils.js +0 -111
- package/lib/esm/middlewares/init-block-studio-router.js +15 -4
- package/lib/esm/plugins/_theme.js +280 -242
- package/lib/esm/tsconfig.tsbuildinfo +1 -1
- package/lib/esm/utils/ts-morph-utils.js +59 -0
- package/lib/esm/utils/zod-utils.js +0 -73
- package/lib/types/tsconfig.tsbuildinfo +1 -1
- package/lib/types/utils/ts-morph-utils.d.ts +9 -0
- package/lib/types/utils/zod-utils.d.ts +0 -16
- package/package.json +4 -4
|
@@ -32,12 +32,23 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
32
32
|
return result;
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
35
38
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
39
|
exports.createTsMorphProject = createTsMorphProject;
|
|
37
40
|
exports.extractTypeWithDependencies = extractTypeWithDependencies;
|
|
38
41
|
exports.combineTypeDefinitions = combineTypeDefinitions;
|
|
42
|
+
exports.tsFileToZodSchema = tsFileToZodSchema;
|
|
43
|
+
const config_1 = __importDefault(require("@blocklet/sdk/lib/config"));
|
|
44
|
+
const fs_1 = require("fs");
|
|
45
|
+
const lowerFirst_1 = __importDefault(require("lodash/lowerFirst"));
|
|
46
|
+
const nanoid_1 = require("nanoid");
|
|
39
47
|
const path = __importStar(require("path"));
|
|
40
48
|
const ts_morph_1 = require("ts-morph");
|
|
49
|
+
const ts_to_zod_1 = require("ts-to-zod");
|
|
50
|
+
const zod_1 = require("zod");
|
|
51
|
+
const helper_1 = require("./helper");
|
|
41
52
|
/**
|
|
42
53
|
* 创建 ts-morph 项目
|
|
43
54
|
* @param tsConfigFilePath tsconfig.json 文件路径
|
|
@@ -253,3 +264,55 @@ function combineTypeDefinitions(typeText, dependencies, imports = []) {
|
|
|
253
264
|
combinedText += typeText;
|
|
254
265
|
return combinedText;
|
|
255
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* 从TypeScript文件中的类型声明生成Zod schema
|
|
269
|
+
* 支持处理外部引用类型
|
|
270
|
+
* @param sourceFilePath 源文件路径
|
|
271
|
+
* @param typeName 类型名称
|
|
272
|
+
* @param tsConfigFilePath tsconfig.json 路径,默认为项目根目录下的tsconfig.json
|
|
273
|
+
*/
|
|
274
|
+
async function tsFileToZodSchema(sourceFilePath, typeName) {
|
|
275
|
+
try {
|
|
276
|
+
const { typeText, dependencies, imports } = extractTypeWithDependencies(sourceFilePath, typeName);
|
|
277
|
+
// set imports to empty array
|
|
278
|
+
const combinedTypeDefinition = combineTypeDefinitions(typeText, dependencies, []);
|
|
279
|
+
// 使用 ts-to-zod 生成代码,需要手动添加 imports 和 combinedTypeDefinition,因为 zod-to-ts 对 import 处理存在问题
|
|
280
|
+
const result = (0, ts_to_zod_1.generate)({
|
|
281
|
+
sourceText: combinedTypeDefinition,
|
|
282
|
+
keepComments: true,
|
|
283
|
+
});
|
|
284
|
+
// 提取生成的 Zod schema 代码
|
|
285
|
+
const zodSchemaText = result.getZodSchemasFile('zod');
|
|
286
|
+
// 创建临时目录
|
|
287
|
+
const tmpDir = path.resolve(config_1.default.env.dataDir, 'temp');
|
|
288
|
+
try {
|
|
289
|
+
await fs_1.promises.stat(tmpDir);
|
|
290
|
+
}
|
|
291
|
+
catch (error) {
|
|
292
|
+
// 如果目录不存在,stat 会抛出错误
|
|
293
|
+
await fs_1.promises.mkdir(tmpDir, { recursive: true });
|
|
294
|
+
}
|
|
295
|
+
const fileName = `zodSchema_${typeName}_${(0, nanoid_1.nanoid)(helper_1.NANOID_LENGTH)}.ts`;
|
|
296
|
+
const filePath = path.join(tmpDir, fileName);
|
|
297
|
+
// 添加 ts-to-zod 的 imports 和 zodSchemaText
|
|
298
|
+
const zodSchemaTextWithImports = `
|
|
299
|
+
${imports.join('\n')}
|
|
300
|
+
|
|
301
|
+
${zodSchemaText}
|
|
302
|
+
`;
|
|
303
|
+
// 写入临时文件
|
|
304
|
+
await fs_1.promises.writeFile(filePath, zodSchemaTextWithImports);
|
|
305
|
+
// 首字母转换为小写
|
|
306
|
+
const schemaName = `${(0, lowerFirst_1.default)(typeName)}Schema`;
|
|
307
|
+
const module = await Promise.resolve(`${filePath}`).then(s => __importStar(require(s)));
|
|
308
|
+
const schema = module[schemaName];
|
|
309
|
+
// 清理临时文件
|
|
310
|
+
await fs_1.promises.unlink(filePath);
|
|
311
|
+
return schema;
|
|
312
|
+
}
|
|
313
|
+
catch (error) {
|
|
314
|
+
console.error('Failed to generate Zod schema from TypeScript file:', error);
|
|
315
|
+
console.error('Error details:', error);
|
|
316
|
+
return zod_1.z.object({}).passthrough();
|
|
317
|
+
}
|
|
318
|
+
}
|
|
@@ -1,59 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
-
};
|
|
38
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
3
|
exports.PROPERTIES_TYPE_SCHEMA = void 0;
|
|
40
4
|
exports.propertiesToZodSchema = propertiesToZodSchema;
|
|
41
5
|
exports.jsonSchemaToProperties = jsonSchemaToProperties;
|
|
42
6
|
exports.zodSchemaToTypeString = zodSchemaToTypeString;
|
|
43
7
|
exports.zodSchemaToJsonSchema = zodSchemaToJsonSchema;
|
|
44
|
-
exports.tsFileToZodSchema = tsFileToZodSchema;
|
|
45
|
-
exports.tsFileInterfaceToProperties = tsFileInterfaceToProperties;
|
|
46
|
-
const config_1 = __importDefault(require("@blocklet/sdk/lib/config"));
|
|
47
|
-
const fs_1 = require("fs");
|
|
48
|
-
const lowerFirst_1 = __importDefault(require("lodash/lowerFirst"));
|
|
49
8
|
const nanoid_1 = require("nanoid");
|
|
50
|
-
const path = __importStar(require("path"));
|
|
51
|
-
const ts_to_zod_1 = require("ts-to-zod");
|
|
52
9
|
const zod_1 = require("zod");
|
|
53
10
|
const zod_to_json_schema_1 = require("zod-to-json-schema");
|
|
54
11
|
const zod_to_ts_1 = require("zod-to-ts");
|
|
55
12
|
const helper_1 = require("./helper");
|
|
56
|
-
const ts_morph_utils_1 = require("./ts-morph-utils");
|
|
57
13
|
const PROPERTY_PREFIX = '@description';
|
|
58
14
|
const JOIN_SYMBOL = ' | ';
|
|
59
15
|
// 转换为: type: string | visible: boolean
|
|
@@ -245,70 +201,3 @@ function zodSchemaToTypeString(schema, typeName, removeUndefined = true) {
|
|
|
245
201
|
function zodSchemaToJsonSchema(schema) {
|
|
246
202
|
return (0, zod_to_json_schema_1.zodToJsonSchema)(schema, { $refStrategy: 'none' });
|
|
247
203
|
}
|
|
248
|
-
/**
|
|
249
|
-
* 从TypeScript文件中的类型声明生成Zod schema
|
|
250
|
-
* 支持处理外部引用类型
|
|
251
|
-
* @param sourceFilePath 源文件路径
|
|
252
|
-
* @param typeName 类型名称
|
|
253
|
-
* @param tsConfigFilePath tsconfig.json 路径,默认为项目根目录下的tsconfig.json
|
|
254
|
-
*/
|
|
255
|
-
async function tsFileToZodSchema(sourceFilePath, typeName) {
|
|
256
|
-
try {
|
|
257
|
-
const { typeText, dependencies, imports } = (0, ts_morph_utils_1.extractTypeWithDependencies)(sourceFilePath, typeName);
|
|
258
|
-
// set imports to empty array
|
|
259
|
-
const combinedTypeDefinition = (0, ts_morph_utils_1.combineTypeDefinitions)(typeText, dependencies, []);
|
|
260
|
-
// 使用 ts-to-zod 生成代码,需要手动添加 imports 和 combinedTypeDefinition,因为 zod-to-ts 对 import 处理存在问题
|
|
261
|
-
const result = (0, ts_to_zod_1.generate)({
|
|
262
|
-
sourceText: combinedTypeDefinition,
|
|
263
|
-
keepComments: true,
|
|
264
|
-
});
|
|
265
|
-
// 提取生成的 Zod schema 代码
|
|
266
|
-
const zodSchemaText = result.getZodSchemasFile('zod');
|
|
267
|
-
// 创建临时目录
|
|
268
|
-
const tmpDir = path.resolve(config_1.default.env.dataDir, 'temp');
|
|
269
|
-
try {
|
|
270
|
-
await fs_1.promises.stat(tmpDir);
|
|
271
|
-
}
|
|
272
|
-
catch (error) {
|
|
273
|
-
// 如果目录不存在,stat 会抛出错误
|
|
274
|
-
await fs_1.promises.mkdir(tmpDir, { recursive: true });
|
|
275
|
-
}
|
|
276
|
-
const fileName = `zodSchema_${typeName}_${(0, nanoid_1.nanoid)(helper_1.NANOID_LENGTH)}.ts`;
|
|
277
|
-
const filePath = path.join(tmpDir, fileName);
|
|
278
|
-
// 添加 ts-to-zod 的 imports 和 zodSchemaText
|
|
279
|
-
const zodSchemaTextWithImports = `
|
|
280
|
-
${imports.join('\n')}
|
|
281
|
-
|
|
282
|
-
${zodSchemaText}
|
|
283
|
-
`;
|
|
284
|
-
// 写入临时文件
|
|
285
|
-
await fs_1.promises.writeFile(filePath, zodSchemaTextWithImports);
|
|
286
|
-
// 动态导入生成的模块
|
|
287
|
-
const module = await Promise.resolve(`${`file://${filePath}`}`).then(s => __importStar(require(s)));
|
|
288
|
-
// 首字母转换为小写
|
|
289
|
-
const schemaName = `${(0, lowerFirst_1.default)(typeName)}Schema`;
|
|
290
|
-
// 获取 schema
|
|
291
|
-
const schema = module[schemaName];
|
|
292
|
-
// 清理临时文件
|
|
293
|
-
await fs_1.promises.unlink(filePath);
|
|
294
|
-
return schema;
|
|
295
|
-
}
|
|
296
|
-
catch (error) {
|
|
297
|
-
console.error('Failed to generate Zod schema from TypeScript file:', error);
|
|
298
|
-
console.error('Error details:', error);
|
|
299
|
-
return zod_1.z.object({}).passthrough();
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* 从TypeScript文件中的类型生成Properties对象
|
|
304
|
-
* 支持处理外部引用类型
|
|
305
|
-
* @param sourceFilePath 源文件路径
|
|
306
|
-
* @param typeName 类型名称
|
|
307
|
-
* @param existingProperties 已存在的properties对象
|
|
308
|
-
*/
|
|
309
|
-
async function tsFileInterfaceToProperties(sourceFilePath, typeName, existingProperties = {}) {
|
|
310
|
-
const zodSchema = await tsFileToZodSchema(sourceFilePath, typeName);
|
|
311
|
-
const jsonSchema = zodSchemaToJsonSchema(zodSchema);
|
|
312
|
-
// get jsonSchemaToProperties and set isRoot to true
|
|
313
|
-
return jsonSchemaToProperties(jsonSchema, { existingProperties, key: '', isRoot: true });
|
|
314
|
-
}
|
|
@@ -8,7 +8,8 @@ import { METADATA_FILE_NAME, NEW_BLOCK_TEMPLATE_PATH, NEW_BLOCK_TEMPLATE_METADAT
|
|
|
8
8
|
// 导入Zod相关工具
|
|
9
9
|
import { findBlockPropsInterface } from '../utils/block-props-utils';
|
|
10
10
|
import { isPathSafe, isDev, downloadAsset, isMetadataFile, getPreviewImageRelativePath, initializeMetadata, findComponentFiles, getBlockStudioInfo, getBlockCode, getBlockEntryFilesPattern, safeParse, } from '../utils/helper';
|
|
11
|
-
import {
|
|
11
|
+
import { tsFileToZodSchema } from '../utils/ts-morph-utils';
|
|
12
|
+
import { propertiesToZodSchema, zodSchemaToTypeString, zodSchemaToJsonSchema, jsonSchemaToProperties, } from '../utils/zod-utils';
|
|
12
13
|
export const initBlockStudioRouter = Router();
|
|
13
14
|
const BINARY_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.gif', '.webp', '.ico', '.svg'];
|
|
14
15
|
// 共享的请求验证和文件路径处理
|
|
@@ -82,7 +83,7 @@ initBlockStudioRouter.post('/', async (req, res) => {
|
|
|
82
83
|
try {
|
|
83
84
|
const dir = path.dirname(filePath);
|
|
84
85
|
if (!fs.existsSync(dir)) {
|
|
85
|
-
|
|
86
|
+
throw new Error('Directory not found');
|
|
86
87
|
}
|
|
87
88
|
const currentMetadata = initializeMetadata(filePath);
|
|
88
89
|
const mergedContent = { ...currentMetadata, ...content };
|
|
@@ -152,7 +153,7 @@ initBlockStudioRouter.post('/create', async (req, res) => {
|
|
|
152
153
|
return res.status(500).json({ error: 'Failed to create block' });
|
|
153
154
|
}
|
|
154
155
|
});
|
|
155
|
-
initBlockStudioRouter.get('/
|
|
156
|
+
initBlockStudioRouter.get('/resources', async (req, res) => {
|
|
156
157
|
const { withBlockletData = true } = req.query;
|
|
157
158
|
const allBlocks = await findComponentFiles();
|
|
158
159
|
// get code to metadata
|
|
@@ -181,6 +182,10 @@ initBlockStudioRouter.get('/all', async (req, res) => {
|
|
|
181
182
|
}
|
|
182
183
|
return res.json(keyBy(allBlocksWithCode, 'id'));
|
|
183
184
|
});
|
|
185
|
+
initBlockStudioRouter.get('/components', async (_req, res) => {
|
|
186
|
+
const allBlocks = await findComponentFiles();
|
|
187
|
+
return res.json(allBlocks);
|
|
188
|
+
});
|
|
184
189
|
// 统一的属性到接口转换端点 - 可以预览或生成
|
|
185
190
|
initBlockStudioRouter.post('/properties-to-interface', async (req, res) => {
|
|
186
191
|
const write = req.body.write === true;
|
|
@@ -269,7 +274,13 @@ initBlockStudioRouter.post('/interface-to-properties', async (req, res) => {
|
|
|
269
274
|
return res.status(404).json({ success: false, error: 'BlockProps interface not found or could not be parsed' });
|
|
270
275
|
}
|
|
271
276
|
try {
|
|
272
|
-
const
|
|
277
|
+
const zodSchema = await tsFileToZodSchema(componentPath, 'BlockProps');
|
|
278
|
+
const jsonSchema = zodSchemaToJsonSchema(zodSchema);
|
|
279
|
+
const newProperties = jsonSchemaToProperties(jsonSchema, {
|
|
280
|
+
existingProperties: currentMetadata.properties || {},
|
|
281
|
+
key: '',
|
|
282
|
+
isRoot: true,
|
|
283
|
+
});
|
|
273
284
|
// 如果请求要求写入文件
|
|
274
285
|
if (write) {
|
|
275
286
|
// 更新元数据
|